Skip to content

Commit 6e9a5e4

Browse files
authored
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
1 parent 1416850 commit 6e9a5e4

File tree

4 files changed

+42
-8
lines changed

4 files changed

+42
-8
lines changed

bintool/bintool.cpp

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,21 @@ std::unique_ptr<block> find_first_block(std::vector<uint8_t> bin, uint32_t stora
192192
}
193193

194194

195+
void set_block_ignored(elf_file *elf, uint32_t block_addr) {
196+
auto seg = elf->segment_from_physical_address(block_addr);
197+
if (seg == nullptr) {
198+
fail(ERROR_NOT_POSSIBLE, "The ELF file does not contain the block address %x", block_addr);
199+
}
200+
std::vector<uint8_t> content = elf->content(*seg);
201+
uint32_t offset = block_addr + 4 - seg->physical_address();
202+
if ((content[offset] & 0x7f) != PICOBIN_BLOCK_ITEM_PARTITION_TABLE) {
203+
DEBUG_LOG("setting block at %08x to ignored\n", block_addr);
204+
content[offset] = 0x7e;
205+
}
206+
elf->content(*seg, content);
207+
}
208+
209+
195210
void set_next_block(elf_file *elf, std::unique_ptr<block> &first_block, uint32_t highest_address) {
196211
// todo this isn't right, but virtual should be physical for now
197212
auto seg = elf->segment_from_physical_address(first_block->physical_addr);
@@ -214,6 +229,15 @@ void set_next_block(elf_file *elf, std::unique_ptr<block> &first_block, uint32_t
214229
}
215230

216231

232+
void set_block_ignored(std::vector<uint8_t> &bin, uint32_t storage_addr, uint32_t block_addr) {
233+
uint32_t offset = block_addr + 4 - storage_addr;
234+
if ((bin[offset] & 0x7f) != PICOBIN_BLOCK_ITEM_PARTITION_TABLE) {
235+
DEBUG_LOG("setting block at %08x to ignored\n", block_addr);
236+
bin[offset] = 0x7e;
237+
}
238+
}
239+
240+
217241
void set_next_block(std::vector<uint8_t> &bin, uint32_t storage_addr, std::unique_ptr<block> &first_block, uint32_t highest_address) {
218242
// todo this isn't right, but virtual should be physical for now
219243
uint32_t offset = first_block->physical_addr + first_block->next_block_rel_index * 4 - storage_addr;
@@ -230,7 +254,7 @@ void set_next_block(std::vector<uint8_t> &bin, uint32_t storage_addr, std::uniqu
230254
}
231255

232256

233-
block place_new_block(elf_file *elf, std::unique_ptr<block> &first_block) {
257+
block place_new_block(elf_file *elf, std::unique_ptr<block> &first_block, bool set_others_ignored) {
234258
uint32_t highest_ram_address = 0;
235259
uint32_t highest_flash_address = 0;
236260
bool no_flash = false;
@@ -265,8 +289,10 @@ block place_new_block(elf_file *elf, std::unique_ptr<block> &first_block) {
265289
set_next_block(elf, first_block, highest_address);
266290
loop_start_rel = -first_block->next_block_rel;
267291
new_block_addr = first_block->physical_addr + first_block->next_block_rel;
292+
if (set_others_ignored) set_block_ignored(elf, first_block->physical_addr);
268293
} else {
269294
DEBUG_LOG("There is already a block loop\n");
295+
if (set_others_ignored) set_block_ignored(elf, first_block->physical_addr);
270296
uint32_t next_block_addr = first_block->physical_addr + first_block->next_block_rel;
271297
while (true) {
272298
auto segment = elf->segment_from_physical_address(next_block_addr);
@@ -300,6 +326,7 @@ block place_new_block(elf_file *elf, std::unique_ptr<block> &first_block) {
300326
break;
301327
} else {
302328
DEBUG_LOG("Continue looping\n");
329+
if (set_others_ignored) set_block_ignored(elf, new_first_block->physical_addr);
303330
next_block_addr = new_first_block->physical_addr + new_first_block->next_block_rel;
304331
new_first_block.reset();
305332
}
@@ -399,7 +426,7 @@ std::unique_ptr<block> get_last_block(std::vector<uint8_t> &bin, uint32_t storag
399426
}
400427

401428

402-
block place_new_block(std::vector<uint8_t> &bin, uint32_t storage_addr, std::unique_ptr<block> &first_block) {
429+
block place_new_block(std::vector<uint8_t> &bin, uint32_t storage_addr, std::unique_ptr<block> &first_block, bool set_others_ignored) {
403430
uint32_t highest_ram_address = 0;
404431
uint32_t highest_flash_address = 0;
405432
bool no_flash = false;
@@ -431,9 +458,14 @@ block place_new_block(std::vector<uint8_t> &bin, uint32_t storage_addr, std::uni
431458
set_next_block(bin, storage_addr, first_block, highest_address);
432459
loop_start_rel = -first_block->next_block_rel;
433460
new_block_addr = first_block->physical_addr + first_block->next_block_rel;
461+
if (set_others_ignored) set_block_ignored(bin, storage_addr, first_block->physical_addr);
434462
} else {
435463
DEBUG_LOG("Ooh, there is already a block loop - lets find it's end\n");
436-
new_first_block = get_last_block(bin, storage_addr, first_block);
464+
auto all_blocks = get_all_blocks(bin, storage_addr, first_block);
465+
for (auto &block : all_blocks) {
466+
if (set_others_ignored) set_block_ignored(bin, storage_addr, block->physical_addr);
467+
}
468+
new_first_block = std::move(all_blocks.back());
437469
set_next_block(bin, storage_addr, new_first_block, highest_address);
438470
new_block_addr = new_first_block->physical_addr + new_first_block->next_block_rel;
439471
loop_start_rel = first_block->physical_addr - new_block_addr;

bintool/bintool.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ typedef enum verified_t {
2222

2323
// Elfs
2424
std::unique_ptr<block> find_first_block(elf_file *elf);
25-
block place_new_block(elf_file *elf, std::unique_ptr<block> &first_block);
25+
block place_new_block(elf_file *elf, std::unique_ptr<block> &first_block, bool set_others_ignored=false);
2626
#if HAS_MBEDTLS
2727
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);
2828
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 @@ typedef std::function<void(std::vector<uint8_t> &bin, uint32_t offset, uint32_t
3434
std::unique_ptr<block> find_first_block(std::vector<uint8_t> bin, uint32_t storage_addr);
3535
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);
3636
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);
37-
block place_new_block(std::vector<uint8_t> &bin, uint32_t storage_addr, std::unique_ptr<block> &first_block);
37+
block place_new_block(std::vector<uint8_t> &bin, uint32_t storage_addr, std::unique_ptr<block> &first_block, bool set_others_ignored=false);
3838
uint32_t calc_checksum(std::vector<uint8_t> bin);
3939
#if HAS_MBEDTLS
4040
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);

bintool/metadata.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ struct partition_table_item : public single_byte_size_item {
208208
}
209209
if (name.size() > 0) {
210210
char size = name.size();
211-
assert(size & 0x7f == size);
211+
assert((size & 0x7f) == size);
212212
std::vector<char> name_vec = {size};
213213
for (char c : name) {
214214
name_vec.push_back(c);

main.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4914,7 +4914,8 @@ void sign_guts_elf(elf_file* elf, private_t private_key, public_t public_key) {
49144914
}
49154915
}
49164916

4917-
block new_block = place_new_block(elf, first_block);
4917+
// Workaround RP2350-E13, which means when using rollback versions, all other blocks must be set as ignored
4918+
block new_block = place_new_block(elf, first_block, settings.seal.rollback_version);
49184919

49194920
if (settings.seal.set_tbyb) {
49204921
// Set the TBYB bit on the image_type_item
@@ -5000,7 +5001,8 @@ vector<uint8_t> sign_guts_bin(iostream_memory_access in, private_t private_key,
50005001
}
50015002
}
50025003

5003-
block new_block = place_new_block(bin, bin_start, first_block);
5004+
// Workaround RP2350-E13, which means when using rollback versions, all other blocks must be set as ignored
5005+
block new_block = place_new_block(bin, bin_start, first_block, settings.seal.rollback_version);
50045006

50055007
if (settings.seal.major_version || settings.seal.minor_version || settings.seal.rollback_version) {
50065008
std::shared_ptr<version_item> version = new_block.get_item<version_item>();

0 commit comments

Comments
 (0)