mirror of https://github.com/wolfSSL/wolfBoot.git
132 lines
4.0 KiB
Python
132 lines
4.0 KiB
Python
"""
|
|
Parse IFWI Image to compute initial PCR0 value as obtained by Intel Boot Guard
|
|
"""
|
|
import struct
|
|
import argparse
|
|
import hashlib
|
|
import os
|
|
import re
|
|
import subprocess
|
|
|
|
FLASH_SIZE_IN_MB = 64
|
|
|
|
def off_to_addr(off: int, image_size : int = FLASH_SIZE_IN_MB*1024*1024) -> int:
|
|
"""
|
|
convert offset in the image to address in memory
|
|
"""
|
|
return (4 * 1024 * 1024 * 1024) - (image_size - off)
|
|
|
|
def addr_to_off(addr:int, image_size : int = FLASH_SIZE_IN_MB*1024*1024) -> int:
|
|
"""
|
|
convert address in memory to offset in the image
|
|
"""
|
|
return image_size - ((4 * 1024 * 1024 * 1024) - addr)
|
|
|
|
def get_sha256_hash(data: bytearray) -> bytearray:
|
|
"""
|
|
return the sha256 of data
|
|
"""
|
|
h = hashlib.sha256()
|
|
h.update(data)
|
|
return h.digest()
|
|
|
|
def get_config_value(config: str, name):
|
|
"""
|
|
Parse config to find line of type NAME=value, return value
|
|
"""
|
|
|
|
pattern = rf'^{re.escape(name)}=(.*)$'
|
|
matches = re.findall(pattern, config, re.MULTILINE)
|
|
if matches:
|
|
return matches[0].strip()
|
|
return None
|
|
|
|
def get_sha256_hash_of_wolfboot_image(file_path: str):
|
|
"""
|
|
Get sha256 hash of wolfboot image at file_path
|
|
"""
|
|
HDR_OFF = 8
|
|
WOLFBOOT_SHA_HDR = 0x03
|
|
with open(file_path, 'rb') as f:
|
|
data = f.read()
|
|
data = data[HDR_OFF:]
|
|
while True:
|
|
if data[0] == 0xff:
|
|
data = data[1:]
|
|
continue
|
|
t, l = struct.unpack('<HH', data[:4])
|
|
if l == 0:
|
|
return None
|
|
if t == WOLFBOOT_SHA_HDR:
|
|
return data[4:4+l]
|
|
data = data[4+l:]
|
|
|
|
def get_sym_addr(elf_file: str, sym_name: str) -> int:
|
|
"""
|
|
get the address of a symbol from ELF file
|
|
"""
|
|
symbols = subprocess.check_output(['nm', elf_file]).split(b'\n')
|
|
matches = list(filter(lambda x: sym_name.encode() in x, symbols))
|
|
if not matches:
|
|
return None
|
|
return int(matches[0].split(b' ')[0], 16)
|
|
|
|
def get_keystore_sym_addr() -> int:
|
|
"""
|
|
get the address of symbol keystore from ELF file image
|
|
"""
|
|
return get_sym_addr('stage1/loader_stage1.elf', '_start_keystore')
|
|
|
|
def pcr_extend(pcr: bytearray, data: bytearray) -> bytearray:
|
|
"""
|
|
get value of extend operation on pcr with data
|
|
"""
|
|
return get_sha256_hash(pcr + data)
|
|
|
|
if __name__ == '__main__':
|
|
if os.path.exists('.config'):
|
|
with open('.config', 'r', encoding='utf-8') as f:
|
|
config = f.read()
|
|
else:
|
|
print("The file .config does not exist.")
|
|
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('image_file', type=str, help='Path to the image file')
|
|
parser.add_argument('--target', type=str, choices=['IBG', 'qemu'],
|
|
default='IBG', help='Target platform')
|
|
|
|
args = parser.parse_args()
|
|
image = bytes()
|
|
|
|
with open(args.image_file, 'rb') as f:
|
|
image = bytearray(f.read())
|
|
|
|
pcr0 = bytearray(b'\x00'*32)
|
|
if args.target == 'qemu':
|
|
# self_extend_pcr() in boot_x86_fsp.c
|
|
# Hashes from _start_keystore to end of 4GB (keystore + vectors)
|
|
keystore_addr = get_keystore_sym_addr()
|
|
keystore_off = addr_to_off(keystore_addr, image_size = len(image))
|
|
ibb = image[keystore_off:]
|
|
pcr0 = pcr_extend(pcr0, get_sha256_hash(ibb))
|
|
|
|
print(f"Initial PCR0: {pcr0.hex()}")
|
|
|
|
is_stage1_auth_enabled = get_config_value(config, 'STAGE1_AUTH') == '1'
|
|
print(f"stage1 auth is {'enabled' if is_stage1_auth_enabled else 'disabled'}")
|
|
|
|
is_measured_boot = get_config_value(config, 'MEASURED_BOOT') == '1'
|
|
|
|
# wolfBoot_image_measure() extends PCR with wolfboot image hash
|
|
if is_measured_boot:
|
|
wb_hash = get_sha256_hash_of_wolfboot_image('stage1/wolfboot_raw_v1_signed.bin')
|
|
pcr0 = pcr_extend(pcr0, wb_hash)
|
|
print(f"PCR0 after wolfboot image measure: {pcr0.hex()}")
|
|
|
|
# the pcrdigest needed by policy_sign tool is the hash of the concatenation of all PCRs involved in the policy.
|
|
# we have only one PCR here
|
|
pcr_digest = get_sha256_hash(pcr0)
|
|
|
|
print("PCR Policy (use with tpm/policy_sign with -pcrdigest arg)")
|
|
print(pcr_digest.hex())
|