Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 14 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ SYNOPSIS:
picotool config [-s <key> <value>] [-g <group>] <filename> [-t <type>]
picotool load [--ignore-partitions] [--family <family_id>] [-p <partition>] [-n] [-N] [-u] [-v] [-x] <filename> [-t <type>] [-o
<offset>] [device-selection]
picotool encrypt [--quiet] [--verbose] [--embed] [--fast-rosc] [--use-mbedtls] [--otp-key-page <page>] [--hash] [--sign] <infile> [-t
<type>] [-o <offset>] <outfile> [-t <type>] <aes_key> <iv_salt> <signing_key> <otp>
picotool seal [--quiet] [--verbose] [--hash] [--sign] [--clear] <infile> [-t <type>] [-o <offset>] <outfile> [-t <type>] <key> <otp>
[--major <major>] [--minor <minor>] [--rollback <rollback> [<rows>..]]
picotool encrypt [--quiet] [--verbose] [--embed] [--fast-rosc] [--use-mbedtls] [--otp-key-page <page>] [--hash] [--sign] [--clear]
[--pin-xip-sram] <infile> [-t <type>] [-o <offset>] <outfile> [-t <type>] <aes_key> <iv_salt> <signing_key> <otp>
picotool seal [--quiet] [--verbose] [--hash] [--sign] [--clear] [--pin-xip-sram] <infile> [-t <type>] [-o <offset>] <outfile> [-t
<type>] <key> <otp> [--major <major>] [--minor <minor>] [--rollback <rollback> [<rows>..]]
picotool link [--quiet] [--verbose] <outfile> [-t <type>] <infile1> [-t <type>] <infile2> [-t <type>] [<infile3>] [-t <type>] [-p <pad>]
picotool save [-p] [-v] [--family <family_id>] <filename> [-t <type>] [device-selection]
picotool save -a [-v] [--family <family_id>] <filename> [-t <type>] [device-selection]
Expand Down Expand Up @@ -578,8 +578,8 @@ SEAL:
Add final metadata to a binary, optionally including a hash and/or signature.

SYNOPSIS:
picotool seal [--quiet] [--verbose] [--hash] [--sign] [--clear] <infile> [-t <type>] [-o <offset>] <outfile> [-t <type>] <key> <otp>
[--major <major>] [--minor <minor>] [--rollback <rollback> [<rows>..]]
picotool seal [--quiet] [--verbose] [--hash] [--sign] [--clear] [--pin-xip-sram] <infile> [-t <type>] [-o <offset>] <outfile> [-t
<type>] <key> <otp> [--major <major>] [--minor <minor>] [--rollback <rollback> [<rows>..]]

OPTIONS:
--quiet
Expand All @@ -603,6 +603,8 @@ OPTIONS:
Sign the file
--clear
Clear all of SRAM on load
--pin-xip-sram
Pin XIP SRAM on load
File to load from
<infile>
The file name
Expand Down Expand Up @@ -648,8 +650,8 @@ ENCRYPT:
Encrypt the program.

SYNOPSIS:
picotool encrypt [--quiet] [--verbose] [--embed] [--fast-rosc] [--use-mbedtls] [--otp-key-page <page>] [--hash] [--sign] <infile> [-t
<type>] [-o <offset>] <outfile> [-t <type>] <aes_key> <iv_salt> <signing_key> <otp>
picotool encrypt [--quiet] [--verbose] [--embed] [--fast-rosc] [--use-mbedtls] [--otp-key-page <page>] [--hash] [--sign] [--clear]
[--pin-xip-sram] <infile> [-t <type>] [-o <offset>] <outfile> [-t <type>] <aes_key> <iv_salt> <signing_key> <otp>

OPTIONS:
--quiet
Expand Down Expand Up @@ -679,6 +681,10 @@ OPTIONS:
Hash the encrypted file
--sign
Sign the encrypted file
--clear
Clear all of SRAM on load
--pin-xip-sram
Pin XIP SRAM on load
File to load from
<infile>
The file name
Expand Down
4 changes: 0 additions & 4 deletions bintool/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,6 @@ cc_library(
"HAS_MBEDTLS=1", # Bazel build always has mbedtls.
],
includes = ["."],
# In the CMake build, there's a workaround where this library is built with
# NO_PICO_PLATFORM, but that define shouldn't propagate to other
# dependencies.
local_defines = ["NO_PICO_PLATFORM=1"],
deps = [
"//elf",
"//errors",
Expand Down
2 changes: 0 additions & 2 deletions bintool/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ if (NOT TARGET mbedtls)
add_library(bintool STATIC
bintool.cpp)
target_compile_definitions(bintool PRIVATE
NO_PICO_PLATFORM=1
HAS_MBEDTLS=0
)

Expand All @@ -18,7 +17,6 @@ else()
bintool.cpp
mbedtls_wrapper.c)
target_compile_definitions(bintool PRIVATE
NO_PICO_PLATFORM=1
HAS_MBEDTLS=1
)

Expand Down
93 changes: 70 additions & 23 deletions bintool/bintool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -687,22 +687,52 @@ void hash_andor_sign_block(block *new_block, const public_t public_key, const pr
}


std::vector<uint8_t> get_lm_hash_data(elf_file *elf, block *new_block, bool clear_sram = false) {
bool check_generic_load_map(std::shared_ptr<load_map_item> load_map, model_t model, bool &pin_xip_sram) {
if (load_map == nullptr) {
return false;
}

// generic xip pinning from the SDK
pin_xip_sram = load_map->entries.size() == 1
&& load_map->entries[0].storage_address == 0x0
&& load_map->entries[0].runtime_address == model->xip_sram_start()
&& load_map->entries[0].size == 0x0;
return pin_xip_sram;
}


std::vector<uint8_t> get_lm_hash_data(elf_file *elf, block *new_block, model_t model, bool clear_sram = false, bool pin_xip_sram = false) {
std::vector<uint8_t> to_hash;
std::shared_ptr<load_map_item> load_map = new_block->get_item<load_map_item>();
if (check_generic_load_map(load_map, model, pin_xip_sram)) {
new_block->items.erase(std::remove(new_block->items.begin(), new_block->items.end(), load_map), new_block->items.end());
load_map = nullptr;
}
if (load_map == nullptr) {
std::vector<load_map_item::entry> entries;
if (clear_sram) {
// todo tidy up this way of hashing the uint32_t
std::vector<uint32_t> sram_size_vec = {SRAM_END_RP2350 - SRAM_START};
std::vector<uint32_t> sram_size_vec = {model->sram_end() - model->sram_start()};
entries.push_back({
0x0,
SRAM_START,
model->sram_start(),
sram_size_vec[0]
});
auto sram_size_data = words_to_lsb_bytes(sram_size_vec.begin(), sram_size_vec.end());
std::copy(sram_size_data.begin(), sram_size_data.end(), std::back_inserter(to_hash));
DEBUG_LOG("CLEAR %08x + %08x\n", (int)SRAM_START, (int)sram_size_vec[0]);
DEBUG_LOG("CLEAR %08x + %08x\n", (int)model->sram_start(), (int)sram_size_vec[0]);
}
if (pin_xip_sram) {
// todo tidy up this way of hashing the uint32_t
std::vector<uint32_t> xip_pin_size_vec = {0x0};
entries.push_back({
0x0,
model->xip_sram_start(),
xip_pin_size_vec[0]
});
auto xip_pin_size_data = words_to_lsb_bytes(xip_pin_size_vec.begin(), xip_pin_size_vec.end());
std::copy(xip_pin_size_data.begin(), xip_pin_size_data.end(), std::back_inserter(to_hash));
DEBUG_LOG("PIN XIP SRAM %08x + %08x\n", (int)model->xip_sram_start(), (int)xip_pin_size_vec[0]);
}
for(const auto &seg : sorted_segs(elf)) {
if (!seg->is_load()) continue;
Expand Down Expand Up @@ -761,24 +791,41 @@ std::vector<uint8_t> get_lm_hash_data(elf_file *elf, block *new_block, bool clea
}


std::vector<uint8_t> get_lm_hash_data(std::vector<uint8_t> bin, uint32_t storage_addr, uint32_t runtime_addr, block *new_block, get_more_bin_cb more_cb, bool clear_sram = false) {
std::vector<uint8_t> get_lm_hash_data(std::vector<uint8_t> bin, uint32_t storage_addr, uint32_t runtime_addr, block *new_block, get_more_bin_cb more_cb, model_t model, bool clear_sram = false, bool pin_xip_sram = false) {
std::vector<uint8_t> to_hash;
std::shared_ptr<load_map_item> load_map = new_block->get_item<load_map_item>();
if (check_generic_load_map(load_map, model, pin_xip_sram)) {
new_block->items.erase(std::remove(new_block->items.begin(), new_block->items.end(), load_map), new_block->items.end());
load_map = nullptr;
}
if (load_map == nullptr) {
to_hash.insert(to_hash.begin(), bin.begin(), bin.end());
std::vector<load_map_item::entry> entries;
if (clear_sram) {
// todo gate this clearing of SRAM
std::vector<uint32_t> sram_size_vec = {0x00082000};
// todo tidy up this way of hashing the uint32_t
std::vector<uint32_t> sram_size_vec = {model->sram_end() - model->sram_start()};
assert(sram_size_vec[0] % 4 == 0);
entries.push_back({
0x0,
0x20000000,
model->sram_start(),
sram_size_vec[0]
});
auto sram_size_data = words_to_lsb_bytes(sram_size_vec.begin(), sram_size_vec.end());
to_hash.insert(to_hash.begin(), sram_size_data.begin(), sram_size_data.end());
std::copy(sram_size_data.begin(), sram_size_data.end(), std::back_inserter(to_hash));
DEBUG_LOG("CLEAR %08x + %08x\n", (int)model->sram_start(), (int)sram_size_vec[0]);
}
if (pin_xip_sram) {
// todo tidy up this way of hashing the uint32_t
std::vector<uint32_t> xip_pin_size_vec = {0x0};
entries.push_back({
0x0,
model->xip_sram_start(),
xip_pin_size_vec[0]
});
auto xip_pin_size_data = words_to_lsb_bytes(xip_pin_size_vec.begin(), xip_pin_size_vec.end());
std::copy(xip_pin_size_data.begin(), xip_pin_size_data.end(), std::back_inserter(to_hash));
DEBUG_LOG("PIN XIP SRAM %08x + %08x\n", (int)model->xip_sram_start(), (int)xip_pin_size_vec[0]);
}
to_hash.insert(to_hash.begin(), bin.begin(), bin.end());
DEBUG_LOG("HASH %08x + %08x\n", (int)storage_addr, (int)bin.size());
entries.push_back(
{
Expand Down Expand Up @@ -823,8 +870,8 @@ std::vector<uint8_t> get_lm_hash_data(std::vector<uint8_t> bin, uint32_t storage
}


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) {
std::vector<uint8_t> to_hash = get_lm_hash_data(elf, new_block, clear_sram);
int hash_andor_sign(elf_file *elf, block *new_block, const public_t public_key, const private_t private_key, model_t model, bool hash_value, bool sign, bool clear_sram, bool pin_xip_sram) {
std::vector<uint8_t> to_hash = get_lm_hash_data(elf, new_block, model, clear_sram, pin_xip_sram);

hash_andor_sign_block(new_block, public_key, private_key, hash_value, sign, to_hash);

Expand Down Expand Up @@ -858,8 +905,8 @@ int hash_andor_sign(elf_file *elf, block *new_block, const public_t public_key,
}


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) {
std::vector<uint8_t> to_hash = get_lm_hash_data(bin, storage_addr, runtime_addr, new_block, nullptr, clear_sram);
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, model_t model, bool hash_value, bool sign, bool clear_sram, bool pin_xip_sram) {
std::vector<uint8_t> to_hash = get_lm_hash_data(bin, storage_addr, runtime_addr, new_block, nullptr, model, clear_sram, pin_xip_sram);

hash_andor_sign_block(new_block, public_key, private_key, hash_value, sign, to_hash);

Expand All @@ -872,15 +919,15 @@ std::vector<uint8_t> hash_andor_sign(std::vector<uint8_t> bin, uint32_t storage_
}


void verify_block(std::vector<uint8_t> bin, uint32_t storage_addr, uint32_t runtime_addr, block *block, verified_t &hash_verified, verified_t &sig_verified, get_more_bin_cb more_cb) {
void verify_block(std::vector<uint8_t> bin, uint32_t storage_addr, uint32_t runtime_addr, block *block, model_t model, verified_t &hash_verified, verified_t &sig_verified, get_more_bin_cb more_cb) {
std::shared_ptr<load_map_item> load_map = block->get_item<load_map_item>();
std::shared_ptr<hash_def_item> hash_def = block->get_item<hash_def_item>();
hash_verified = none;
sig_verified = none;
if (load_map == nullptr || hash_def == nullptr) {
return;
}
std::vector<uint8_t> to_hash = get_lm_hash_data(bin, storage_addr, runtime_addr, block, more_cb, false);
std::vector<uint8_t> to_hash = get_lm_hash_data(bin, storage_addr, runtime_addr, block, more_cb, model);

// auto it = std::find(block->items.begin(), block->items.end(), hash_def);
// assert (it != block->items.end());
Expand Down Expand Up @@ -941,8 +988,8 @@ void verify_block(std::vector<uint8_t> bin, uint32_t storage_addr, uint32_t runt
}


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) {
std::vector<uint8_t> to_enc = get_lm_hash_data(elf, new_block);
void encrypt_guts(elf_file *elf, block *new_block, const aes_key_t aes_key, model_t model, std::vector<uint8_t> &iv_data, std::vector<uint8_t> &enc_data) {
std::vector<uint8_t> to_enc = get_lm_hash_data(elf, new_block, model);

std::random_device rand{};
assert(rand.max() - rand.min() >= 256);
Expand All @@ -966,11 +1013,11 @@ void encrypt_guts(elf_file *elf, block *new_block, const aes_key_t aes_key, std:
}


int encrypt(elf_file *elf, block *new_block, const aes_key_t aes_key, const public_t public_key, const private_t private_key, std::vector<uint8_t> iv_salt, bool hash_value, bool sign) {
int encrypt(elf_file *elf, block *new_block, const aes_key_t aes_key, const public_t public_key, const private_t private_key, model_t model, std::vector<uint8_t> iv_salt, bool hash_value, bool sign) {

std::vector<uint8_t> iv_data;
std::vector<uint8_t> enc_data;
encrypt_guts(elf, new_block, aes_key, iv_data, enc_data);
encrypt_guts(elf, new_block, aes_key, model, iv_data, enc_data);

// Salt IV
assert(iv_data.size() == iv_salt.size());
Expand Down Expand Up @@ -1054,13 +1101,13 @@ int encrypt(elf_file *elf, block *new_block, const aes_key_t aes_key, const publ
new_block->items.erase(std::remove(new_block->items.begin(), new_block->items.end(), load_map), new_block->items.end());
}

hash_andor_sign(elf, new_block, public_key, private_key, hash_value, sign);
hash_andor_sign(elf, new_block, public_key, private_key, model, hash_value, sign);

return 0;
}


std::vector<uint8_t> encrypt(std::vector<uint8_t> bin, uint32_t storage_addr, uint32_t runtime_addr, block *new_block, const aes_key_t aes_key, const public_t public_key, const private_t private_key, std::vector<uint8_t> iv_salt, bool hash_value, bool sign) {
std::vector<uint8_t> encrypt(std::vector<uint8_t> bin, uint32_t storage_addr, uint32_t runtime_addr, block *new_block, const aes_key_t aes_key, const public_t public_key, const private_t private_key, model_t model, std::vector<uint8_t> iv_salt, bool hash_value, bool sign) {
std::random_device rand{};
assert(rand.max() - rand.min() >= 256);

Expand Down Expand Up @@ -1114,6 +1161,6 @@ std::vector<uint8_t> encrypt(std::vector<uint8_t> bin, uint32_t storage_addr, ui
new_block->items.erase(std::remove(new_block->items.begin(), new_block->items.end(), load_map), new_block->items.end());
}

return hash_andor_sign(bin, storage_addr, runtime_addr, new_block, public_key, private_key, hash_value, sign);;
return hash_andor_sign(bin, storage_addr, runtime_addr, new_block, public_key, private_key, model, hash_value, sign);
}
#endif
13 changes: 7 additions & 6 deletions bintool/bintool.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#endif
#include "elf_file.h"
#include "metadata.h"
#include "model.h"

typedef enum verified_t {
none,
Expand All @@ -24,9 +25,9 @@ typedef enum verified_t {
std::unique_ptr<block> find_first_block(elf_file *elf);
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);
int encrypt(elf_file *elf, block *new_block, const aes_key_t aes_key, const public_t public_key, const private_t private_key, std::vector<uint8_t> iv_salt, bool hash_value, bool sign);
int hash_andor_sign(elf_file *elf, block *new_block, const public_t public_key, const private_t private_key, model_t model, bool hash_value, bool sign, bool clear_sram = false, bool pin_xip_sram = false);
void encrypt_guts(elf_file *elf, block *new_block, const aes_key_t aes_key, model_t model, std::vector<uint8_t> &iv_data, std::vector<uint8_t> &enc_data);
int encrypt(elf_file *elf, block *new_block, const aes_key_t aes_key, const public_t public_key, const private_t private_key, model_t model, std::vector<uint8_t> iv_salt, bool hash_value, bool sign);
#endif

// Bins
Expand All @@ -37,7 +38,7 @@ std::vector<std::unique_ptr<block>> get_all_blocks(std::vector<uint8_t> &bin, ui
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);
std::vector<uint8_t> encrypt(std::vector<uint8_t> bin, uint32_t storage_addr, uint32_t runtime_addr, block *new_block, const aes_key_t aes_key, const public_t public_key, const private_t private_key, std::vector<uint8_t> iv_salt, bool hash_value, bool sign);
void verify_block(std::vector<uint8_t> bin, uint32_t storage_addr, uint32_t runtime_addr, block *block, verified_t &hash_verified, verified_t &sig_verified, get_more_bin_cb more_cb = nullptr);
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, model_t model, bool hash_value, bool sign, bool clear_sram = false, bool pin_xip_sram = false);
std::vector<uint8_t> encrypt(std::vector<uint8_t> bin, uint32_t storage_addr, uint32_t runtime_addr, block *new_block, const aes_key_t aes_key, const public_t public_key, const private_t private_key, model_t model, std::vector<uint8_t> iv_salt, bool hash_value, bool sign);
void verify_block(std::vector<uint8_t> bin, uint32_t storage_addr, uint32_t runtime_addr, block *block, model_t model, verified_t &hash_verified, verified_t &sig_verified, get_more_bin_cb more_cb = nullptr);
#endif
Loading
Loading