Ignore other blocks when signing with rollback version (#237)
* Ignore first block when signing with rollback version
* Ignore all blocks (except partition tables), not just first block
* Rename ignore_others -> set_others_ignored
diff --git a/bintool/bintool.cpp b/bintool/bintool.cpp
index e75c0b0..5cf7318 100644
--- a/bintool/bintool.cpp
+++ b/bintool/bintool.cpp
@@ -192,6 +192,21 @@
}
+void set_block_ignored(elf_file *elf, uint32_t block_addr) {
+ auto seg = elf->segment_from_physical_address(block_addr);
+ if (seg == nullptr) {
+ fail(ERROR_NOT_POSSIBLE, "The ELF file does not contain the block address %x", block_addr);
+ }
+ std::vector<uint8_t> content = elf->content(*seg);
+ uint32_t offset = block_addr + 4 - seg->physical_address();
+ if ((content[offset] & 0x7f) != PICOBIN_BLOCK_ITEM_PARTITION_TABLE) {
+ DEBUG_LOG("setting block at %08x to ignored\n", block_addr);
+ content[offset] = 0x7e;
+ }
+ elf->content(*seg, content);
+}
+
+
void set_next_block(elf_file *elf, std::unique_ptr<block> &first_block, uint32_t highest_address) {
// todo this isn't right, but virtual should be physical for now
auto seg = elf->segment_from_physical_address(first_block->physical_addr);
@@ -214,6 +229,15 @@
}
+void set_block_ignored(std::vector<uint8_t> &bin, uint32_t storage_addr, uint32_t block_addr) {
+ uint32_t offset = block_addr + 4 - storage_addr;
+ if ((bin[offset] & 0x7f) != PICOBIN_BLOCK_ITEM_PARTITION_TABLE) {
+ DEBUG_LOG("setting block at %08x to ignored\n", block_addr);
+ bin[offset] = 0x7e;
+ }
+}
+
+
void set_next_block(std::vector<uint8_t> &bin, uint32_t storage_addr, std::unique_ptr<block> &first_block, uint32_t highest_address) {
// todo this isn't right, but virtual should be physical for now
uint32_t offset = first_block->physical_addr + first_block->next_block_rel_index * 4 - storage_addr;
@@ -230,7 +254,7 @@
}
-block place_new_block(elf_file *elf, std::unique_ptr<block> &first_block) {
+block place_new_block(elf_file *elf, std::unique_ptr<block> &first_block, bool set_others_ignored) {
uint32_t highest_ram_address = 0;
uint32_t highest_flash_address = 0;
bool no_flash = false;
@@ -265,8 +289,10 @@
set_next_block(elf, first_block, highest_address);
loop_start_rel = -first_block->next_block_rel;
new_block_addr = first_block->physical_addr + first_block->next_block_rel;
+ if (set_others_ignored) set_block_ignored(elf, first_block->physical_addr);
} else {
DEBUG_LOG("There is already a block loop\n");
+ if (set_others_ignored) set_block_ignored(elf, first_block->physical_addr);
uint32_t next_block_addr = first_block->physical_addr + first_block->next_block_rel;
while (true) {
auto segment = elf->segment_from_physical_address(next_block_addr);
@@ -300,6 +326,7 @@
break;
} else {
DEBUG_LOG("Continue looping\n");
+ if (set_others_ignored) set_block_ignored(elf, new_first_block->physical_addr);
next_block_addr = new_first_block->physical_addr + new_first_block->next_block_rel;
new_first_block.reset();
}
@@ -399,7 +426,7 @@
}
-block place_new_block(std::vector<uint8_t> &bin, uint32_t storage_addr, std::unique_ptr<block> &first_block) {
+block place_new_block(std::vector<uint8_t> &bin, uint32_t storage_addr, std::unique_ptr<block> &first_block, bool set_others_ignored) {
uint32_t highest_ram_address = 0;
uint32_t highest_flash_address = 0;
bool no_flash = false;
@@ -431,9 +458,14 @@
set_next_block(bin, storage_addr, first_block, highest_address);
loop_start_rel = -first_block->next_block_rel;
new_block_addr = first_block->physical_addr + first_block->next_block_rel;
+ if (set_others_ignored) set_block_ignored(bin, storage_addr, first_block->physical_addr);
} else {
DEBUG_LOG("Ooh, there is already a block loop - lets find it's end\n");
- new_first_block = get_last_block(bin, storage_addr, first_block);
+ auto all_blocks = get_all_blocks(bin, storage_addr, first_block);
+ for (auto &block : all_blocks) {
+ if (set_others_ignored) set_block_ignored(bin, storage_addr, block->physical_addr);
+ }
+ new_first_block = std::move(all_blocks.back());
set_next_block(bin, storage_addr, new_first_block, highest_address);
new_block_addr = new_first_block->physical_addr + new_first_block->next_block_rel;
loop_start_rel = first_block->physical_addr - new_block_addr;
diff --git a/bintool/bintool.h b/bintool/bintool.h
index c4ddbec..20029ac 100644
--- a/bintool/bintool.h
+++ b/bintool/bintool.h
@@ -22,7 +22,7 @@
// Elfs
std::unique_ptr<block> find_first_block(elf_file *elf);
-block place_new_block(elf_file *elf, std::unique_ptr<block> &first_block);
+block place_new_block(elf_file *elf, std::unique_ptr<block> &first_block, bool set_others_ignored=false);
#if HAS_MBEDTLS
int hash_andor_sign(elf_file *elf, block *new_block, const public_t public_key, const private_t private_key, bool hash_value, bool sign, bool clear_sram = false);
void encrypt_guts(elf_file *elf, block *new_block, const aes_key_t aes_key, std::vector<uint8_t> &iv_data, std::vector<uint8_t> &enc_data);
@@ -34,7 +34,7 @@
std::unique_ptr<block> find_first_block(std::vector<uint8_t> bin, uint32_t storage_addr);
std::unique_ptr<block> get_last_block(std::vector<uint8_t> &bin, uint32_t storage_addr, std::unique_ptr<block> &first_block, get_more_bin_cb more_cb = nullptr);
std::vector<std::unique_ptr<block>> get_all_blocks(std::vector<uint8_t> &bin, uint32_t storage_addr, std::unique_ptr<block> &first_block, get_more_bin_cb more_cb = nullptr);
-block place_new_block(std::vector<uint8_t> &bin, uint32_t storage_addr, std::unique_ptr<block> &first_block);
+block place_new_block(std::vector<uint8_t> &bin, uint32_t storage_addr, std::unique_ptr<block> &first_block, bool set_others_ignored=false);
uint32_t calc_checksum(std::vector<uint8_t> bin);
#if HAS_MBEDTLS
std::vector<uint8_t> hash_andor_sign(std::vector<uint8_t> bin, uint32_t storage_addr, uint32_t runtime_addr, block *new_block, const public_t public_key, const private_t private_key, bool hash_value, bool sign, bool clear_sram = false);
diff --git a/bintool/metadata.h b/bintool/metadata.h
index a01e048..76aed8b 100644
--- a/bintool/metadata.h
+++ b/bintool/metadata.h
@@ -208,7 +208,7 @@
}
if (name.size() > 0) {
char size = name.size();
- assert(size & 0x7f == size);
+ assert((size & 0x7f) == size);
std::vector<char> name_vec = {size};
for (char c : name) {
name_vec.push_back(c);
diff --git a/main.cpp b/main.cpp
index 44e7d91..61617fd 100644
--- a/main.cpp
+++ b/main.cpp
@@ -4914,7 +4914,8 @@
}
}
- block new_block = place_new_block(elf, first_block);
+ // Workaround RP2350-E13, which means when using rollback versions, all other blocks must be set as ignored
+ block new_block = place_new_block(elf, first_block, settings.seal.rollback_version);
if (settings.seal.set_tbyb) {
// Set the TBYB bit on the image_type_item
@@ -5000,7 +5001,8 @@
}
}
- block new_block = place_new_block(bin, bin_start, first_block);
+ // Workaround RP2350-E13, which means when using rollback versions, all other blocks must be set as ignored
+ block new_block = place_new_block(bin, bin_start, first_block, settings.seal.rollback_version);
if (settings.seal.major_version || settings.seal.minor_version || settings.seal.rollback_version) {
std::shared_ptr<version_item> version = new_block.get_item<version_item>();