Skip to content

Commit cbf9d39

Browse files
matetothpalnvlsianpu
authored andcommitted
travis: Add documentation to FIH CI test
Change-Id: Ib0def822e9748d64fd0dd77eefaaeba4ceaf1a83 Signed-off-by: Mate Toth-Pal <[email protected]>
1 parent d4f6053 commit cbf9d39

File tree

1 file changed

+127
-0
lines changed

1 file changed

+127
-0
lines changed

docs/design.md

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1159,3 +1159,130 @@ this, the target must provide a definition for the `boot_save_shared_data()`
11591159
function which is declared in `boot/bootutil/include/bootutil/boot_record.h`.
11601160
The `boot_add_data_to_shared_area()` function can be used for adding new TLV
11611161
entries to the shared data area.
1162+
1163+
## [Testing in CI](#testing-in-ci)
1164+
1165+
### [Testing Fault Injection Hardening (FIH)](#testing-fih)
1166+
1167+
The CI currently tests the Fault Injection Hardening feature of MCUboot by
1168+
executing instruction skip during execution, and looking at whether a corrupted
1169+
image was booted by the bootloader or not.
1170+
1171+
The main idea is that instruction skipping can be automated by scripting a
1172+
debugger to automatically execute the following steps:
1173+
1174+
- Set breakpoint at specified address.
1175+
- Continue execution.
1176+
- On breakpoint hit increase the Program Counter.
1177+
- Continue execution.
1178+
- Detach from target after a timeout reached.
1179+
1180+
Whether or not the corrupted image was booted or not can be decided by looking
1181+
for certain entries in the log.
1182+
1183+
As MCUboot is deployed on a microcontroller, testing FI would not make much
1184+
sense in the simulator environment running on a host machine with different
1185+
architecture than the MCU's, as the degree of hardening depends on compiler
1186+
behavior. For example, (a bit counterintuitively) the code produced by gcc
1187+
with `-O0` optimisation is more resilient against FI attacks than the code
1188+
generated with `-O3` or `-Os` optimizations.
1189+
1190+
To run on a desired architecture in the CI, the tests need to be executed on an
1191+
emulator (as real devices are not available in the CI environment). For this
1192+
implementation QEMU is selected.
1193+
1194+
For the tests MCUboot needs a set of drivers and an implementation of a main
1195+
function. For the purpose of this test Trusted-Firmware-M has been selected as
1196+
it supports Armv8-M platforms that are also emulated by QEMU.
1197+
1198+
The tests run in a docker container inside the CI VMs, to make it more easy to
1199+
deploy build and test environment (QEMU, compilers, interpreters). The CI VMs
1200+
seems to be using quite old Ubuntu (16.04).
1201+
1202+
The sequence of the testing is the following (pseudo code):
1203+
1204+
```sh
1205+
fn main()
1206+
# Implemented in ci/fih-tests_install.sh
1207+
generate_docker_image(Dockerfile)
1208+
1209+
# See details below. Implemented in ci/fih-tests_run.sh.
1210+
# Calling the function with different parameters is done by Travis CI based on
1211+
# the values provided in the .travis.yaml
1212+
start_docker_image(skip_sizes, build_type, damage_type, fih_level)
1213+
1214+
fn start_docker_image(skip_sizes, build_type, damage_type, fih_level)
1215+
# implemented in ci/fih_test_docker/execute_test.sh
1216+
compile_mcuboot(build_type)
1217+
1218+
# implemented in ci/fih_test_docker/damage_image.py
1219+
damage_image(damage_type)
1220+
1221+
# implemented in ci/fih_test_docker/run_fi_test.sh
1222+
ranges = generate_address_ranges()
1223+
for s in skip_sizes
1224+
for r in ranges
1225+
do_skip_in_qemu(s, r) # See details below
1226+
evaluate_logs()
1227+
1228+
fn do_skip_in_qemu(size, range)
1229+
for a in r
1230+
run_qemu(a, size) # See details below
1231+
1232+
# this part is implemented in ci/fih_test_docker/fi_tester_gdb.sh
1233+
fn run_qemu(a, size)
1234+
script = create_debugger_script(a, size)
1235+
start_qemu_in_bacground() # logs serial out to a file
1236+
gdb_attach_to_qemu(script)
1237+
kill_qemu()
1238+
1239+
# This checks the debugger and the quemu logs, and decides whether the tets
1240+
# was executed successfully, and whether the image is booted or not. Then
1241+
# emits a yaml fragment on the standard out to be processed by the caller
1242+
# script
1243+
evaluate_run(qemu_log_file)
1244+
```
1245+
1246+
Further notes:
1247+
1248+
- The image is corrupted by changing its signature.
1249+
- MCUBOOT_FIH_PROFILE_MAX is not tested as it requires TRNG, and the AN521
1250+
platform has no support for it. However this profile adds the random
1251+
execution delay to the code, so should not affect the instruction skip results
1252+
too much, because break point is placed at exact address. But in practice this
1253+
makes harder the accurate timing of the attack.
1254+
- The test cases defined in .travis.yml always return `passed`, if they were
1255+
executed successfully. A yaml file is created during test execution with the
1256+
details of the test execution results. A summary of the collected results is
1257+
printed in the log at the end of the test.
1258+
1259+
An advantage of having the tests running in a docker image is that it is
1260+
possible to run the tests on a local machine that has git and docker, without
1261+
installing any additional software.
1262+
1263+
So, running the test on the host looks like the following (The commands below
1264+
are issued from the MCUboot source directory):
1265+
1266+
```sh
1267+
$ ./ci/fih-tests_install.sh
1268+
$ FIH_LEVEL=MCUBOOT_FIH_PROFILE_MEDIUM BUILD_TYPE=RELEASE SKIP_SIZE=2 \
1269+
DAMAGE_TYPE=SIGNATURE ./ci/fih-tests_run.sh
1270+
```
1271+
On the travis CI the environment variables in the last command are set based on
1272+
the configs provided in the `.travis.yaml`
1273+
1274+
This starts the tests, however the shell that it is running in is not
1275+
interactive, it is not possible to examine the results of the test run. To have
1276+
an interactive shell where the results can be examined, the following can be
1277+
done:
1278+
1279+
- The docker image needs to be built with `ci/fih-tests_install.sh` as described
1280+
above.
1281+
- Start the docker image with the following command:
1282+
`docker run -i -t mcuboot/fih-test`.
1283+
- Execute the test with a command similar to the following:
1284+
`/root/execute_test.sh 8 RELEASE SIGNATURE MEDIUM`. After the test finishes,
1285+
the shell returns, and it is possible to investigate the results. It is also
1286+
possible to stop the test with _Ctrl+c_. The parameters to the
1287+
`execute_test.sh` are `SKIP_SIZE`, `BUILD_TYPE`, `DAMAGE_TYPE`, `FIH_LEVEL` in
1288+
order.

0 commit comments

Comments
 (0)