mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-08-05 13:26:57 +00:00
fix(core): fix bootloader monotonic check during upgrade
[no changelog]
This commit is contained in:
parent
2a0a8b3b3c
commit
2bd3b6ff06
@ -50,10 +50,10 @@
|
||||
#define BOOTUCB_SECTOR_END 0xE
|
||||
|
||||
// Non-boardloader area (includes bootloader, firmware, assets and storage)
|
||||
#define NONBLDR_START (0x0C01E000)
|
||||
#define NONBLDR_MAXSIZE (497 * 8 * 1024) // 3976 kB
|
||||
#define NONBLDR_SECTOR_START 0xF
|
||||
#define NONBLDR_SECTOR_END 0x1FF
|
||||
#define NONBOARDLOADER_START (0x0C01E000)
|
||||
#define NONBOARDLOADER_MAXSIZE (497 * 8 * 1024) // 3976 kB
|
||||
#define NONBOARDLOADER_SECTOR_START 0xF
|
||||
#define NONBOARDLOADER_SECTOR_END 0x1FF
|
||||
|
||||
#define BOOTLOADER_START (0x0C01E000)
|
||||
#define BOOTLOADER_MAXSIZE (32 * 8 * 1024) // 256 kB
|
||||
|
@ -19,10 +19,10 @@ BOOTUCB_START = 0xc01c000;
|
||||
BOOTUCB_MAXSIZE = 0x2000;
|
||||
BOOTUCB_SECTOR_START = 0xe;
|
||||
BOOTUCB_SECTOR_END = 0xe;
|
||||
NONBLDR_START = 0xc01e000;
|
||||
NONBLDR_MAXSIZE = 0x3e2000;
|
||||
NONBLDR_SECTOR_START = 0xf;
|
||||
NONBLDR_SECTOR_END = 0x1ff;
|
||||
NONBOARDLOADER_START = 0xc01e000;
|
||||
NONBOARDLOADER_MAXSIZE = 0x3e2000;
|
||||
NONBOARDLOADER_SECTOR_START = 0xf;
|
||||
NONBOARDLOADER_SECTOR_END = 0x1ff;
|
||||
BOOTLOADER_START = 0xc01e000;
|
||||
BOOTLOADER_MAXSIZE = 0x40000;
|
||||
BOOTLOADER_SECTOR_START = 0xf;
|
||||
|
@ -50,10 +50,10 @@
|
||||
#define BOOTUCB_SECTOR_END 0xE
|
||||
|
||||
// Non-boardloader area (includes bootloader, firmware, assets and storage)
|
||||
#define NONBLDR_START (0x0C01E000)
|
||||
#define NONBLDR_MAXSIZE (497 * 8 * 1024) // 3976 kB
|
||||
#define NONBLDR_SECTOR_START 0xF
|
||||
#define NONBLDR_SECTOR_END 0x1FF
|
||||
#define NONBOARDLOADER_START (0x0C01E000)
|
||||
#define NONBOARDLOADER_MAXSIZE (497 * 8 * 1024) // 3976 kB
|
||||
#define NONBOARDLOADER_SECTOR_START 0xF
|
||||
#define NONBOARDLOADER_SECTOR_END 0x1FF
|
||||
|
||||
#define BOOTLOADER_START (0x0C01E000)
|
||||
#define BOOTLOADER_MAXSIZE (32 * 8 * 1024) // 256 kB
|
||||
|
@ -19,10 +19,10 @@ BOOTUCB_START = 0xc01c000;
|
||||
BOOTUCB_MAXSIZE = 0x2000;
|
||||
BOOTUCB_SECTOR_START = 0xe;
|
||||
BOOTUCB_SECTOR_END = 0xe;
|
||||
NONBLDR_START = 0xc01e000;
|
||||
NONBLDR_MAXSIZE = 0x3e2000;
|
||||
NONBLDR_SECTOR_START = 0xf;
|
||||
NONBLDR_SECTOR_END = 0x1ff;
|
||||
NONBOARDLOADER_START = 0xc01e000;
|
||||
NONBOARDLOADER_MAXSIZE = 0x3e2000;
|
||||
NONBOARDLOADER_SECTOR_START = 0xf;
|
||||
NONBOARDLOADER_SECTOR_END = 0x1ff;
|
||||
BOOTLOADER_START = 0xc01e000;
|
||||
BOOTLOADER_MAXSIZE = 0x40000;
|
||||
BOOTLOADER_SECTOR_START = 0xf;
|
||||
|
@ -131,7 +131,7 @@ board_capabilities_t capabilities
|
||||
|
||||
#ifdef USE_BOOT_UCB
|
||||
|
||||
static void try_to_upgrade(void) {
|
||||
static void try_bootloader_update(void) {
|
||||
boot_ucb_t ucb;
|
||||
|
||||
// Start with some non-deterministic delay
|
||||
@ -143,7 +143,7 @@ static void try_to_upgrade(void) {
|
||||
}
|
||||
|
||||
// Check if the new boot header is present and valid
|
||||
const boot_header_t* hdr = boot_header_check_integrity(ucb.header_address);
|
||||
const boot_header_auth_t* hdr = boot_header_auth_get(ucb.header_address);
|
||||
if (hdr == NULL) {
|
||||
return;
|
||||
}
|
||||
@ -167,7 +167,7 @@ static void try_to_upgrade(void) {
|
||||
|
||||
// Check if the new bootloader is the same as the old one
|
||||
// (just prevents unnecessary flash erase/write)
|
||||
if (bootloader_is_unchanged(hdr, code_address)) {
|
||||
if (sectrue != bootloader_area_needs_update(hdr, code_address)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -240,8 +240,8 @@ static inline void ensure_signed_bootloader(
|
||||
fih_delay(0);
|
||||
|
||||
// Check if the boot header is present and valid
|
||||
const boot_header_t* hdr = boot_header_check_integrity(BOOTLOADER_START);
|
||||
fih_ensure(sectrue * (hdr != NULL), "invalid bootloader header");
|
||||
const boot_header_auth_t* hdr = boot_header_auth_get(BOOTLOADER_START);
|
||||
fih_ensure(sectrue * (hdr != NULL), "invalid boot header");
|
||||
|
||||
// Get address of the bootloader code
|
||||
uint32_t code_address = BOOTLOADER_START + hdr->header_size;
|
||||
@ -326,7 +326,7 @@ int main(void) {
|
||||
#ifdef USE_BOOT_UCB
|
||||
// Try to update the bootloader from the UCB (update control block) if it
|
||||
// is present, valid and points to a new valid/signed bootloader image.
|
||||
try_to_upgrade();
|
||||
try_bootloader_update();
|
||||
#endif
|
||||
|
||||
// Address of the next stage to jump to. It's set at the end of
|
||||
|
@ -40,7 +40,7 @@ static void prodtest_bootloader_version(cli_t *cli) {
|
||||
|
||||
mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_BOOTUPDATE);
|
||||
|
||||
const boot_header_t *hdr = boot_header_check_integrity(BOOTLOADER_START);
|
||||
const boot_header_auth_t *hdr = boot_header_auth_get(BOOTLOADER_START);
|
||||
|
||||
if (hdr == NULL) {
|
||||
mpu_restore(mpu_mode);
|
||||
|
@ -60,6 +60,8 @@ DEFINE_SINGLE_AREA(ASSETS_AREA, ASSETS, ACCESS_APP);
|
||||
#endif
|
||||
|
||||
#ifdef USE_BOOT_UCB
|
||||
// Area dedicated to the UCB (Update Control Block) used during
|
||||
// boot-loader or boot-header updates.
|
||||
DEFINE_SINGLE_AREA(BOOTUCB_AREA, BOOTUCB, ACCESS_DEFAULT);
|
||||
#ifdef BOARDLOADER
|
||||
// Area used by the boardloader during bootloader update process.
|
||||
|
@ -35,7 +35,7 @@
|
||||
extern const uint8_t _bootloader_code_size;
|
||||
|
||||
typedef union {
|
||||
boot_header_t hdr;
|
||||
boot_header_auth_t hdr;
|
||||
uint8_t raw[BOOT_HEADER_MAXSIZE];
|
||||
} boot_header_padded_t;
|
||||
|
||||
@ -100,17 +100,17 @@ static const uint8_t * const BOARDLOADER_EC_KEYS[] = {
|
||||
#endif
|
||||
};
|
||||
|
||||
secbool boot_header_check_signature(const boot_header_t* hdr,
|
||||
secbool boot_header_check_signature(const boot_header_auth_t* hdr,
|
||||
const merkle_proof_node_t* merkle_root) {
|
||||
// Get the signature indices based on the signature mask
|
||||
_Static_assert(ARRAY_LENGTH(BOARDLOADER_PQ_KEYS) <= 3);
|
||||
_Static_assert(ARRAY_LENGTH(BOARDLOADER_EC_KEYS) ==
|
||||
ARRAY_LENGTH(BOARDLOADER_PQ_KEYS));
|
||||
|
||||
uint32_t sigmask = hdr->sigmask;
|
||||
uint32_t sigmask_inv = 0; // FIH
|
||||
uint8_t sigmask = hdr->sigmask;
|
||||
uint8_t sigmask_inv = 0; // FIH
|
||||
|
||||
const boot_header_unauth_t* sig = boot_header_get_unauth(hdr);
|
||||
const boot_header_unauth_t* sig = boot_header_unauth_get(hdr);
|
||||
|
||||
for (int sig_idx = 0; sig_idx < ARRAY_LENGTH(sig->ec_signature); sig_idx++) {
|
||||
// Get the index of the public key in the signature mask
|
||||
@ -193,8 +193,8 @@ static const boot_header_merkle_proof_t* boot_header_get_merkle_proof(
|
||||
return proof;
|
||||
}
|
||||
|
||||
const boot_header_t* boot_header_check_integrity(uint32_t address) {
|
||||
boot_header_t* hdr = (boot_header_t*)address;
|
||||
const boot_header_auth_t* boot_header_auth_get(uint32_t address) {
|
||||
boot_header_auth_t* hdr = (boot_header_auth_t*)address;
|
||||
|
||||
// Check if the header starts with the magic
|
||||
if (hdr->magic != BOOT_HEADER_MAGIC_TRZQ) {
|
||||
@ -248,7 +248,8 @@ const boot_header_t* boot_header_check_integrity(uint32_t address) {
|
||||
return hdr;
|
||||
}
|
||||
|
||||
const boot_header_unauth_t* boot_header_get_unauth(const boot_header_t* hdr) {
|
||||
const boot_header_unauth_t* boot_header_unauth_get(
|
||||
const boot_header_auth_t* hdr) {
|
||||
const boot_header_merkle_proof_t* proof = boot_header_get_merkle_proof(hdr);
|
||||
|
||||
if (proof == NULL) {
|
||||
@ -272,7 +273,7 @@ const boot_header_unauth_t* boot_header_get_unauth(const boot_header_t* hdr) {
|
||||
return unauth;
|
||||
}
|
||||
|
||||
void boot_header_calc_merkle_root(const boot_header_t* hdr,
|
||||
void boot_header_calc_merkle_root(const boot_header_auth_t* hdr,
|
||||
uint32_t code_address,
|
||||
merkle_proof_node_t* root) {
|
||||
IMAGE_HASH_CTX ctx;
|
||||
@ -310,18 +311,18 @@ void boot_header_calc_merkle_root(const boot_header_t* hdr,
|
||||
}
|
||||
}
|
||||
|
||||
secbool bootloader_is_unchanged(const boot_header_t* hdr,
|
||||
secbool bootloader_area_needs_update(const boot_header_auth_t* hdr,
|
||||
uint32_t code_address) {
|
||||
boot_header_t* prev_hdr = (boot_header_t*)BOOTLOADER_START;
|
||||
boot_header_auth_t* prev_hdr = (boot_header_auth_t*)BOOTLOADER_START;
|
||||
if (hdr->header_size == prev_hdr->header_size &&
|
||||
hdr->code_size == prev_hdr->code_size &&
|
||||
(memcmp(hdr, prev_hdr, hdr->header_size) == 0) &&
|
||||
(memcmp((const uint8_t*)code_address,
|
||||
(const uint8_t*)prev_hdr + prev_hdr->header_size,
|
||||
hdr->code_size) == 0)) {
|
||||
return sectrue;
|
||||
}
|
||||
return secfalse;
|
||||
}
|
||||
return sectrue;
|
||||
}
|
||||
|
||||
#endif // SECURE_MODE
|
||||
|
@ -221,15 +221,15 @@ void boot_image_replace(const boot_image_t *image) {
|
||||
#else
|
||||
|
||||
bool boot_image_check(const boot_image_t *image) {
|
||||
if (image->image_size < sizeof(boot_header_t)) {
|
||||
if (image->image_size < sizeof(boot_header_auth_t)) {
|
||||
// Invalid image size, must be at least the size of the header
|
||||
return false;
|
||||
}
|
||||
|
||||
mpu_mode_t mode = mpu_reconfig(MPU_MODE_BOOTUPDATE);
|
||||
|
||||
boot_header_t *cur_hdr = (boot_header_t *)BOOTLOADER_START;
|
||||
boot_header_t *new_hdr = (boot_header_t *)image->image_ptr;
|
||||
boot_header_auth_t *cur_hdr = (boot_header_auth_t *)BOOTLOADER_START;
|
||||
boot_header_auth_t *new_hdr = (boot_header_auth_t *)image->image_ptr;
|
||||
|
||||
bool diff = (cur_hdr->header_size != new_hdr->header_size) ||
|
||||
(memcmp(cur_hdr, new_hdr, cur_hdr->header_size) != 0);
|
||||
@ -243,25 +243,29 @@ void boot_image_replace(const boot_image_t *image) {
|
||||
uint32_t header_address = (uint32_t)image->image_ptr;
|
||||
|
||||
// Check that image is big enough to hold the header at least
|
||||
ensure(sectrue * (image->image_size >= sizeof(boot_header_t)),
|
||||
ensure(sectrue * (image->image_size >= sizeof(boot_header_auth_t)),
|
||||
"Bootloader image too small");
|
||||
|
||||
// Read bootloader header
|
||||
const boot_header_t *hdr = boot_header_check_integrity(header_address);
|
||||
const boot_header_auth_t *hdr = boot_header_auth_get(header_address);
|
||||
ensure((hdr != NULL) * sectrue, "Invalid bootloader header");
|
||||
|
||||
// Check the image is big enough to hold both header and code
|
||||
ensure(sectrue * (hdr->header_size <= image->image_size),
|
||||
"Bootloader header too big");
|
||||
ensure(sectrue * (hdr->code_size <= image->image_size),
|
||||
"Bootloader code too big");
|
||||
ensure(sectrue * (hdr->header_size + hdr->code_size <= image->image_size),
|
||||
"Bootloader image too small");
|
||||
|
||||
// Check monotonic version
|
||||
uint8_t min_monotonic_version = 0;
|
||||
ensure(monoctr_read(MONOCTR_BOOTLOADER_VERSION, &min_monotonic_version),
|
||||
"monoctr read");
|
||||
|
||||
mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_BOOTUPDATE);
|
||||
|
||||
const boot_header_auth_t *old_hdr = boot_header_auth_get(BOOTLOADER_START);
|
||||
|
||||
ensure((old_hdr != NULL) * sectrue, "Invalid current bootloader header");
|
||||
|
||||
uint8_t min_monotonic_version = old_hdr->monotonic_version;
|
||||
|
||||
mpu_restore(mpu_mode);
|
||||
|
||||
ensure(sectrue * (hdr->monotonic_version >= min_monotonic_version),
|
||||
"Bootloader downgrade rejected");
|
||||
|
||||
|
@ -42,8 +42,10 @@ extern const void bootloader_size;
|
||||
static const boot_image_t g_bootloader_image = {
|
||||
.image_ptr = (const void *)&bootloader_start,
|
||||
.image_size = (size_t)&bootloader_size,
|
||||
#ifndef USE_BOOT_UCB
|
||||
.hash_00 = BOOTLOADER_00,
|
||||
.hash_FF = BOOTLOADER_FF,
|
||||
#endif
|
||||
};
|
||||
|
||||
const boot_image_t *boot_image_get_embdata(void) { return &g_bootloader_image; }
|
||||
|
@ -65,11 +65,11 @@ secbool boot_ucb_read(boot_ucb_t* ucb) {
|
||||
uint32_t max_address = NONBOARDLOADER_START + NONBOARDLOADER_MAXSIZE;
|
||||
|
||||
if (ucb->header_address < min_address ||
|
||||
ucb->header_address > max_address - sizeof(boot_header_t)) {
|
||||
ucb->header_address > max_address - sizeof(boot_header_auth_t)) {
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
const boot_header_t* hdr = (boot_header_t*)ucb->header_address;
|
||||
const boot_header_auth_t* hdr = (boot_header_auth_t*)ucb->header_address;
|
||||
|
||||
// Get address range where the header and code can be located.
|
||||
// Both header and code must be inside flash area reserved for the
|
||||
@ -116,7 +116,7 @@ secbool boot_ucb_write(uint32_t header_address, uint32_t code_address) {
|
||||
};
|
||||
|
||||
// Calculate the hash of the header
|
||||
boot_header_t* hdr = (boot_header_t*)header_address;
|
||||
boot_header_auth_t* hdr = (boot_header_auth_t*)header_address;
|
||||
|
||||
IMAGE_HASH_CTX ctx;
|
||||
IMAGE_HASH_INIT(&ctx);
|
||||
|
@ -53,6 +53,10 @@ typedef struct {
|
||||
|
||||
/**
|
||||
* Authenticated part of the boot header
|
||||
*
|
||||
* This structure can be extended in future versions if needed.
|
||||
* Just make sure to add new fields at the end of the structure.
|
||||
* Never remove or reorder existing fields.
|
||||
*/
|
||||
typedef struct __attribute__((packed)) {
|
||||
/** Magic constant 'TRZQ' */
|
||||
@ -96,7 +100,7 @@ typedef struct __attribute__((packed)) {
|
||||
* the authenticated part of the header is maximized. */
|
||||
uint8_t padding[0];
|
||||
|
||||
} boot_header_t;
|
||||
} boot_header_auth_t;
|
||||
|
||||
/**
|
||||
* Merkle proof structure used in the boot header to calculate the root
|
||||
@ -147,7 +151,7 @@ typedef struct __attribute__((packed)) {
|
||||
* @param address Address of the boot header in flash memory
|
||||
* @return Pointer to the boot header if valid, NULL otherwise.
|
||||
*/
|
||||
const boot_header_t* boot_header_check_integrity(uint32_t address);
|
||||
const boot_header_auth_t* boot_header_auth_get(uint32_t address);
|
||||
|
||||
/**
|
||||
* Gets pointer to the unauthenticated part of the boot header.
|
||||
@ -169,7 +173,7 @@ const boot_header_unauth_t* boot_header_unauth_get(
|
||||
* @param code_address Address of the bootloader code in flash memory
|
||||
* @param root Pointer to the output Merkle root node
|
||||
*/
|
||||
void boot_header_calc_merkle_root(const boot_header_t* hdr,
|
||||
void boot_header_calc_merkle_root(const boot_header_auth_t* hdr,
|
||||
uint32_t code_address,
|
||||
merkle_proof_node_t* root);
|
||||
|
||||
@ -184,7 +188,7 @@ void boot_header_calc_merkle_root(const boot_header_t* hdr,
|
||||
* @param merkle_root Pointer to the Merkle root
|
||||
* @return secbool indicating whether the signature verification was successful.
|
||||
*/
|
||||
secbool boot_header_check_signature(const boot_header_t* hdr,
|
||||
secbool boot_header_check_signature(const boot_header_auth_t* hdr,
|
||||
const merkle_proof_node_t* merkle_root);
|
||||
|
||||
/**
|
||||
@ -194,7 +198,7 @@ secbool boot_header_check_signature(const boot_header_t* hdr,
|
||||
*
|
||||
* @param hdr Pointer to the new boot header
|
||||
* @param code_address Address of the new bootloader code in flash memory
|
||||
* @return secbool indicating whether the boot header and code are unchanged
|
||||
* @return secbool indicating whether the boot header and code need update
|
||||
*/
|
||||
secbool bootloader_is_unchanged(const boot_header_t* hdr,
|
||||
secbool bootloader_area_needs_update(const boot_header_auth_t* hdr,
|
||||
uint32_t code_address);
|
||||
|
@ -27,9 +27,10 @@
|
||||
typedef struct {
|
||||
const void* image_ptr;
|
||||
size_t image_size;
|
||||
#ifndef USE_BOOT_UCB
|
||||
uint8_t hash_00[32];
|
||||
uint8_t hash_FF[32];
|
||||
|
||||
#endif
|
||||
} boot_image_t;
|
||||
|
||||
/**
|
||||
|
@ -16,11 +16,11 @@ def no_echo(*args, **kwargs):
|
||||
"-D", "--sign-dev-keys", is_flag=True, help="Sign with development header keys."
|
||||
)
|
||||
@click.option(
|
||||
"-d",
|
||||
"--digest",
|
||||
"print_digest",
|
||||
"-m",
|
||||
"--merkle-root",
|
||||
"print_merkle_root",
|
||||
is_flag=True,
|
||||
help="Only output header digest for signing and exit.",
|
||||
help="Only output Merkle root for signing and exit.",
|
||||
)
|
||||
@click.option(
|
||||
"-M",
|
||||
@ -37,7 +37,7 @@ def cli(
|
||||
dry_run,
|
||||
sign_dev_keys,
|
||||
merkle_proof,
|
||||
print_digest,
|
||||
print_merkle_root,
|
||||
quiet,
|
||||
):
|
||||
"""Manage firmware headers.
|
||||
@ -64,9 +64,10 @@ def cli(
|
||||
f"Could not parse file (magic bytes: {magic})"
|
||||
) from e
|
||||
|
||||
digest = fw.digest()
|
||||
if print_digest:
|
||||
click.echo(digest.hex())
|
||||
fw.set_merkle_proof(list(map(bytes.fromhex, merkle_proof)))
|
||||
|
||||
if print_merkle_root:
|
||||
click.echo(fw.merkle_root().hex())
|
||||
return
|
||||
|
||||
if quiet:
|
||||
@ -74,9 +75,6 @@ def cli(
|
||||
else:
|
||||
echo = click.echo
|
||||
|
||||
# Add 16 items
|
||||
fw.set_merkle_proof(list(map(bytes.fromhex, merkle_proof)))
|
||||
|
||||
echo("Signing with dev keys...", err=True)
|
||||
fw.sign_with_devkeys()
|
||||
|
||||
|
@ -477,7 +477,7 @@ class BootloaderV2Image(firmware.BootableImage):
|
||||
# digest is calculated from
|
||||
self.header.sigmask = (1 << 0) | (1 << 1)
|
||||
|
||||
digest = self.digest()
|
||||
digest = self.merkle_root()
|
||||
|
||||
# SLH signature signs the image digest
|
||||
for idx, key in enumerate(self.DEV_PRIVATE_PQ_KEYS):
|
||||
@ -504,13 +504,14 @@ class BootloaderV2Image(firmware.BootableImage):
|
||||
|
||||
output = [
|
||||
"Firmware Header " + _format_container(header_out),
|
||||
f"Fingerprint: {click.style(self.digest().hex(), bold=True)}",
|
||||
f"Leaf hash: {click.style(self.leaf_hash().hex(), bold=True)}",
|
||||
f"Merkle root: {click.style(self.merkle_root().hex(), bold=True)}",
|
||||
]
|
||||
|
||||
return "\n".join(output)
|
||||
|
||||
def verify(self, dev_keys: bool = False) -> None:
|
||||
digest = self.digest()
|
||||
digest = self.merkle_root()
|
||||
|
||||
for idx, key in enumerate(self.public_ec_keys(dev_keys)):
|
||||
if not _ed25519.checkvalid(self.unauth.ec_signatures[idx], digest, key):
|
||||
|
@ -245,7 +245,9 @@ class BootHeader(Struct):
|
||||
"version" / TupleAdapter(c.Int8ul, c.Int8ul, c.Int8ul, c.Int8ul),
|
||||
"fix_version" / TupleAdapter(c.Int8ul, c.Int8ul, c.Int8ul, c.Int8ul),
|
||||
"min_prev_version" / TupleAdapter(c.Int8ul, c.Int8ul, c.Int8ul, c.Int8ul),
|
||||
"monotonic" / c.Int32ul,
|
||||
"monotonic" / c.Int8ul,
|
||||
"sigmask" / c.Int8ul,
|
||||
"_reserved" / c.Padding(2),
|
||||
"header_len" / c.Int32ul,
|
||||
"auth_len" / c.Int32ul,
|
||||
"code_length" / c.Rebuild(
|
||||
@ -255,7 +257,6 @@ class BootHeader(Struct):
|
||||
else (this.code_length or 0)
|
||||
),
|
||||
"storage_address" / c.Int32ul,
|
||||
"sigmask" / c.Int32ul,
|
||||
"firmware_root" / c.Bytes(32),
|
||||
|
||||
# Variable-length padding that's part of the authenticated header
|
||||
@ -319,15 +320,28 @@ class BootableImage(Struct):
|
||||
self.unauth.merkle_proof = proof
|
||||
self.header.auth_len = self.header.header_len - len(self.unauth.build())
|
||||
|
||||
def digest(self) -> bytes:
|
||||
hash_params = self.get_hash_params()
|
||||
hash_fn = hash_params.hash_function
|
||||
def _leaf_value(self) -> bytes:
|
||||
hash_fn = self.get_hash_params().hash_function
|
||||
assert hash_fn is hashlib.sha256 # currently hardcoded in trezorlib.merkle_tree
|
||||
|
||||
auth_header = self.header.build()
|
||||
code_hash = hash_fn(self.code).digest()
|
||||
leaf = auth_header + code_hash
|
||||
return merkle_tree.evaluate_proof(leaf, self.unauth.merkle_proof)
|
||||
return auth_header + code_hash
|
||||
|
||||
def leaf_hash(self) -> bytes:
|
||||
"""Calculate the Merkle leaf hash.
|
||||
|
||||
This is a fingerprint of _this particular_ boot header, which is not affected
|
||||
by other members of the Merkle tree.
|
||||
"""
|
||||
return merkle_tree.leaf_hash(self._leaf_value())
|
||||
|
||||
def merkle_root(self) -> bytes:
|
||||
"""Calculate the Merkle root hash.
|
||||
|
||||
It identifies the entire Merkle tree that contains this boot header. Signatures
|
||||
are evaluated over this value.
|
||||
"""
|
||||
return merkle_tree.evaluate_proof(self._leaf_value(), self.unauth.merkle_proof)
|
||||
|
||||
def model(self) -> Model | None:
|
||||
if isinstance(self.header.hw_model, Model):
|
||||
|
Loading…
Reference in New Issue
Block a user