Browse Source

add initial documentation

S.J.R. van Schaik 4 years ago
commit
128e860201
3 changed files with 524 additions and 0 deletions
  1. 207 0
      design.rst
  2. 176 0
      flashrom.rst
  3. 141 0
      kexec.rst

+ 207 - 0
design.rst

@@ -0,0 +1,207 @@
1
+Trusted Boot
2
+============
3
+
4
+Terminology
5
+-----------
6
+
7
+ * TBM: Trusted Boot Module (the entire system) or Trusted Boot Manager (the ARM Cortex M0 or AVR
8
+   microcontroller).
9
+ * ROTS: read-only trusted state.
10
+
11
+Prerequisites
12
+-------------
13
+
14
+ * SPI NOR Flash to store a minimalistic read-only Linux image without networking support.
15
+ * ARM Cortex M0 or AVR microcontroller.
16
+ * A programmable timer to set deadlines and to trigger an interrupt when these expire.
17
+ * Possibly SPI NOR Flash for the Trusted Boot Module to store information.
18
+ * Key storage and management.
19
+ * The option of image rollback?
20
+
21
+Trust Model
22
+-----------
23
+
24
+There are different trust models that can be used depending on the use case.
25
+These mostly depend on whether the concept of certificate authorities (CAs) is required or not.
26
+Furthermore, the key storage also plays an important role in deciding which of the trust models to
27
+use.
28
+
29
+ #. "Home router"
30
+    CA: none
31
+
32
+    * replace = reflash RO flash
33
+
34
+ #. "Routers in company, sysadmin"
35
+    CA: none
36
+
37
+    * replace = reflash or signed statement
38
+
39
+ #. "Routers with CA"
40
+    CA: one.
41
+
42
+    * replace CA = reflash ROTS
43
+    * replace key = by signed CA statement
44
+
45
+ #. "Routers with multiple CAs"
46
+    CA: multiple.
47
+
48
+    * replace CA = threshold
49
+    * replace key = by signed CA statement.
50
+
51
+ #. "Routers with multiple CAs and initial CA in ROTS"
52
+    CA: multiple.
53
+
54
+    * revoking keys, which is not the same as removing keys.
55
+
56
+ #. CA: multiple.
57
+
58
+    * replace CAs = reflash ROTS.
59
+    * replace key = by signed CA statement
60
+
61
+Key Storage
62
+-----------
63
+
64
+ * RO Flash
65
+ * TBM
66
+ * Box storage (e.g. HDD)
67
+ * Signed statements by embeddeding keys in images.
68
+
69
+Forced reboot
70
+-------------
71
+
72
+Because the image is only trusted up to the extent that the user trusts the parties that have
73
+signed the image, the image may contain vulnerabilities that the user will only be aware of at a
74
+later point.
75
+As these vulnerabilities can be used to compromise the system in such a way that it will prevent
76
+from rebooting the system, it is important that the TBM can reboot the system.
77
+The straightforward method of performing such a forced reboot would be to set a deadline that can
78
+be postponed by the user up to *n* times, whereupon the TBM will simply force a reboot after these
79
+attempts or when the user decides to reboot gracefully.
80
+
81
+Upgrading
82
+---------
83
+
84
+One possible attack vector is that when the image that is running has been compromised in such a
85
+way that it prevents the system from running the update process, even after a reboot, then this
86
+will force the system to always boot the version installed.
87
+To mitigate this we could split up the image into two stages.
88
+The read-only trusted stage will then first boot up a minimalistic environment within the image to
89
+check for updates and to perform them, whereupon the full image will be booted.
90
+Because it is impossible to update the read-only trusted stage as it is stored on a read-only
91
+medium, we want to prevent the read-only stage from being able to perform updates, as it will
92
+require a network stack as well as TLS support.
93
+Both the network stack and TLS support are hard to implement correctly, thus they are both open to
94
+many vulnerabilities that cannot be mitigated as the read-only trusted stage cannot be updated.
95
+This is why the read-only trusted stage cannot be responsible for checking for updates and
96
+performing updates.
97
+Therefore, in combination with the concept of a forced reboot from the TBM, the system would always
98
+be able to check for updates periodically.
99
+
100
+To keep track of the images, a table can be used to mark whether the update stage and the image
101
+itself are known to work.
102
+Based on that table the Trusted Boot Manager can then determine which image to rollback to in case
103
+the updated image does not work.
104
+Furthermore, one important decision is whether to only use images that are known to fully work or
105
+to specifically select working stages separately.
106
+Another important open question is how far back the system is allowed to rollback.
107
+
108
+Initial Keys and Configuration
109
+------------------------------
110
+
111
+The initial key(s) or certificates and the configuration for the TBM could be presented on a SD
112
+card that is inserted before the system is booted for the very first time.
113
+Alternatively, we could decide to have the user embed the keys within the ROTS image before
114
+flashing it to the RO Flash.
115
+Another option would be to offer the user the option of performing key management by means of
116
+serial communication with the Trusted Boot Manager.
117
+
118
+Verification of images
119
+----------------------
120
+
121
+As the user added the keys from the signing parties to trust, the system should only allow images
122
+that have been signed with these keys.
123
+This verification can take place in the read-only trusted stage before booting the image to ensure
124
+that it has not been comprimised.
125
+Furthermore, as there is a notion of reproducible builds, there is the option of verifying the
126
+packages within the image.
127
+However, as the read-only trusted state should be kept simple to avoid any possible vulnerabilities
128
+or compromises, it is better to delegate the responsibility of verifying these packages to the
129
+parties that sign the image.
130
+Similarly, while the idea of sending deltas between different versions of images does sound
131
+beneficial in the sense that the amount of data that has to be downloaded is kept to a minimum,
132
+this would also further complicate the read-only trusted stage to the extent that it could increase
133
+the likelihood of possible vulnerabilities.
134
+
135
+Boot procedure
136
+--------------
137
+
138
+ #. The image from SPI flash is read and booted.
139
+ #. The read-only trusted stage asks the Trusted Boot Manager what to boot and/or asks whether it
140
+    is allowed to boot a certain image.
141
+    By default the read-only trusted stage should boot a semi-trusted update stage.
142
+ #. The read-only trusted stage boots the semi-trusted update stage using ``kexec``.
143
+ #. The semi-trusted update stage checks for updates and downloads a new image if present.
144
+ #. Once downloaded the semi-trusted update stage finishes by telling the Trusted Boot Manager that
145
+    a new image has been downloaded or that no updates were available.
146
+ #. The Trusted Boot Manager reboots the system.
147
+ #. The image from SPI flash is read and booted.
148
+ #. The read-only trusted stage asks the Trusted Boot Manager what to boot and/or asks whether it
149
+    is allowed to boot a certain image.
150
+    After a reboot from the update process, the Trusted Boot Manager will tell the read-only
151
+    trusted stage to boot the latest image.
152
+ #. The read-only trusted stage uses ``kexec`` to boot the latest image.
153
+
154
+Image self-test and rollback
155
+----------------------------
156
+
157
+The image could be extended with a self-test, where the untrusted stage tells the Trusted Boot
158
+Manager that it managed boot successfully.
159
+In case the image fails to boot, the Trusted Boot Manager should set a deadline to expire before
160
+the image is booted.
161
+When this deadline expires, the Trusted Boot Manager can then assume that the image does not work
162
+and should not be used in the future, allowing rollback to the last-known working image.
163
+Furthermore, by solely working with the concept of a last-known working image and an updated image
164
+the possibility of a downgrade is severely limited and no advanced implementation of an image
165
+rollback system would be required.
166
+
167
+Trusted Boot Manager protocol
168
+-----------------------------
169
+
170
+To have the board communicate with the TBM, we have to devise a protocol.
171
+This communication is likely to place over serial communication through the UART ports.
172
+Furthermore, the board can only send requests to the TBM to which the TBM responds, i.e. the TBM
173
+should never be able to initiate communication.
174
+In the read-only trusted stage the Trusted Boot Manager fully trusts the system and as such the
175
+read-only trusted stage can operate using the full scope of the protocol.
176
+At some point the TBM will be informed by the read-only trusted stage that it will boot into
177
+untrusted state, which is an indication for the TBM to configure the deadline timer and that the
178
+scope of the protocol should be limited as the untrusted stage is only allowed to inform the TBM
179
+that it booted successfully.
180
+The read-only trusted stage should be able to ask which images are preferred for booting and if
181
+booting a certain image is allowed.
182
+Furthermore, it would probably be interesting if a list of images that can be booted can be queried
183
+from the TBM.
184
+In the case that we decide to support initial communication from the read-only trusted stage,
185
+either by flashing the RO Flash or by inserting a removable medium such a SD card, it might be
186
+interesting to support this option of configuration in the protocol.
187
+
188
+Proposal(s)
189
+-----------
190
+
191
+To reduce the amount of possible vulnerabilities, the codebase and complexity of the TBM should be
192
+kept as minimalistic as possible.
193
+From that point of view, it would be best that the read-only trusted stage only consists of the
194
+tools necessary to verify signed images, to communicate with the TBM and to ``kexec`` those images.
195
+Furthermore, since the read-only trusted stage cannot be modified once it has been written to the
196
+RO Flash, it cannot be easily patched.
197
+As such, it makes a lot of sense to not include a network and TLS stack, as it is very likely that
198
+they contain many vulnerabilities that have yet to be found.
199
+Separating the update stage from the actual image itself, allows the system to forcefully perform
200
+updates, which would essentially prevent any attacker from extending the time window they have any
201
+further.
202
+However, similar to the read-only trusted stage, the update stage should only come with the tools
203
+necessary to check for updates and to perform an update: a network stack, a TLS stack and tools to
204
+communicate with the TBM.
205
+Finally, from the point of view of maintaining minimalism, only allowing rollback to the last-known
206
+working image of which both the update stage and the image itself is probably one of the most
207
+elegant choices, as it easily prevents downgrade attacks and as it is easier to implement.

+ 176 - 0
flashrom.rst

@@ -0,0 +1,176 @@
1
+..
2
+
3
+Flashing ROMs
4
+=============
5
+
6
+Prerequistes
7
+------------
8
+
9
+ * BusPirate v3.6a
10
+ * SOIC clip
11
+ * Winbond 25Q128FV or any other SPI ROM
12
+
13
+Hooking up the ROM
14
+------------------
15
+
16
+Clip the Winbond 25Q128FV between the SOIC clip. Using the text on the ROM, we can orient the pins on the other side of the clip. The ones on the top from left to right are:
17
+
18
+ * Chip Select (CS)
19
+ * Data Output (DO)
20
+ * Write Protect (WP)
21
+ * Ground (GND)
22
+
23
+The pins on the bottom from left to right are (i.e. the opposite side):
24
+
25
+ * Power Supply (VCC)
26
+ * /HOLD or /RESET
27
+ * Clock (CLK)
28
+ * Data Input (DI)
29
+
30
+Using the colour codes of the wires, we should hook up the pins as follows:
31
+
32
+ * CS <-> White <-> CS
33
+ * MISO <-> Black <-> DO
34
+ * GND <-> Brown <-> GND
35
+ * 5V <-> Orange <-> VCC
36
+ * CLK <-> Purple <-> CLK
37
+ * MOSI <-> Grey <-> DI
38
+
39
+.. code::
40
+        
41
+         VCC H/R CLK  DI
42
+        +-|---|---|---|-+
43
+        |               |
44
+        |    Winbond    |
45
+        |   W25Q128.V   |
46
+        |O              |
47
+        +-|---|---|---|-+
48
+         CS  DO  WP  GND
49
+
50
+Google Flashrom
51
+---------------
52
+
53
+Unlike the mainline version of flashrom, Google's version has two flags to get the name and the
54
+size of the Flash chip:
55
+
56
+.. code::
57
+
58
+        ./flashrom --programmer=buspirate_spi:dev=/dev/buspirate --flash-name
59
+        flashrom v0.9.4  : bc6cab1 : Oct 30 2014 07:32:01 UTC on Linux 4.9.4-gentoo (x86_64), built with libpci 3.1.10, GCC 4.8.x-google 20140307 (prerelease), little endian
60
+        vendor="Macronix" name="MX25L6406E"
61
+        ./flashrom --programmer=buspirate_spi:dev=/dev/buspirate --get-size
62
+        flashrom v0.9.4  : bc6cab1 : Oct 30 2014 07:32:01 UTC on Linux 4.9.4-gentoo (x86_64), built with libpci 3.1.10, GCC 4.8.x-google 20140307 (prerelease), little endian
63
+        8388608
64
+
65
+With the ``layout.txt`` file, we can tag certain regions in the ROM with a custom name:
66
+
67
+.. code::
68
+
69
+        000000:00ffff rw
70
+        7e0000:7fffff ro
71
+
72
+Then we can create two random blobs to verify that the ROM works:
73
+
74
+.. code::
75
+        dd if=/dev/urandom of=rw.dat count=64K bs=1
76
+        dd if=/dev/urandom of=ro.dat count=64K bs=1
77
+
78
+Finally, we can write these two blobs to the two ROM regions by specifying their names.
79
+We also disable parsing the fmap and verifying the unmodified ROM regions to speed up the process.
80
+To maintain an optimal stability an SPI speed of no more than 2 MHz is recommended when using a
81
+BusPirate:
82
+
83
+.. code::
84
+
85
+        ./flashrom --programmer=buspirate_spi:dev=/dev/buspirate -l layout.txt -i ro:ro.dat rw:rw.dat -w --ignore-fmap --fast-verify
86
+
87
+Now that the blobs have been written, we can look at the write-protect ranges supported by the chip:
88
+
89
+.. code::
90
+
91
+        ./flashrom --programmer=buspirate_spi:dev=/dev/buspirate --wp-list
92
+        flashrom v0.9.4  : bc6cab1 : Oct 30 2014 07:32:01 UTC on Linux 4.9.4-gentoo (x86_64), built with libpci 3.1.10, GCC 4.8.x-google 20140307 (prerelease), little endian
93
+        Valid write protection ranges:
94
+        start: 0x000000, length: 0x000000
95
+        start: 0x7e0000, length: 0x020000
96
+        start: 0x7c0000, length: 0x040000
97
+        start: 0x7a0000, length: 0x080000
98
+        start: 0x700000, length: 0x100000
99
+        start: 0x600000, length: 0x200000
100
+        start: 0x400000, length: 0x400000
101
+        start: 0x000000, length: 0x800000
102
+        start: 0x000000, length: 0x800000
103
+        start: 0x000000, length: 0x400000
104
+        start: 0x000000, length: 0x600000
105
+        start: 0x000000, length: 0x700000
106
+        start: 0x000000, length: 0x780000
107
+        start: 0x000000, length: 0x7c0000
108
+        start: 0x000000, length: 0x7e0000
109
+        start: 0x000000, length: 0x800000
110
+
111
+For instance, we can set the write-protect range to be ``0x7e0000`` - ``0x810000``:
112
+
113
+.. code::
114
+
115
+        ./flashrom --programmer=buspirate_spi:dev=/dev/buspirate --wp-range 0x7e0000 0x020000
116
+
117
+After setting the range, we are still able to modify the contents of the entire ROM.
118
+To protect the range, we have to enable write protection as follows:
119
+
120
+.. code::
121
+
122
+        ./flashrom --programmer=buspirate_spi:dev=/dev/buspirate --wp-enable
123
+
124
+``WP#`` must be pulled down for the write protect to be effective, i.e. it must be connected to GND.
125
+This prevents the user from disabling the write protection, changing the write-protected range and
126
+from writing to the write-protected region.
127
+For example, writing a different blob to the region tagged as ``rw`` does work:
128
+
129
+.. code::
130
+
131
+        ./flashrom --programmer=buspirate_spi:dev=/dev/buspirate --layout layout.txt -i rw:ro.dat --write --ignore-fmap --fast-verify
132
+        flashrom v0.9.4  : bc6cab1 : Oct 30 2014 07:32:01 UTC on Linux 4.9.4-gentoo (x86_64), built with libpci 3.1.10, GCC 4.8.x-google 20140307 (prerelease), little endian
133
+        delay loop is unreliable, trying to continue Block protection could not be disabled!
134
+        Erasing and writing flash chip... Verifying flash... VERIFIED.          
135
+        SUCCESS
136
+
137
+While writing a different blob to the region tagged as ``ro`` does not work, as it cannot be erased
138
+due to write-protection:
139
+
140
+.. code::
141
+
142
+        ./flashrom --programmer=buspirate_spi:dev=/dev/buspirate --layout layout.txt -i ro:rw.dat --write --ignore-fmap --fast-verify
143
+        flashrom v0.9.4  : bc6cab1 : Oct 30 2014 07:32:01 UTC on Linux 4.9.4-gentoo (x86_64), built with libpci 3.1.10, GCC 4.8.x-google 20140307 (prerelease), little endian
144
+        delay loop is unreliable, trying to continue Block protection could not be disabled!
145
+        Erasing and writing flash chip... ERASE FAILED at 0x007e0000! Expected=0xff, Read=0x15, failed byte count from 0x007e0000-0x007e0fff: 0xff1
146
+        ERASE FAILED!
147
+        Reading current flash chip contents...
148
+
149
+Furthermore, changing the range is not possible either as long as ``WP#`` is pulled down:
150
+
151
+.. code::
152
+
153
+        ./flashrom --programmer=buspirate_spi:spispeed=2M,dev=/dev/buspirate --layout layout.txt --wp-range 0x000000 0x000000
154
+        flashrom v0.9.4  : bc6cab1 : Oct 30 2014 07:32:01 UTC on Linux 4.9.4-gentoo (x86_64), built with libpci 3.1.10, GCC 4.8.x-google 20140307 (prerelease), little endian
155
+        expected=0x80, but actual=0x9a.
156
+        FAILED
157
+
158
+Finally, disabling the write-protection feature is not possible either as long as ``WP#`` is pulled
159
+down:
160
+
161
+.. code::
162
+
163
+        ./flashrom --programmer=buspirate_spi:spispeed=2M,dev=/dev/buspirate --layout layout.txt --wp-disable
164
+        flashrom v0.9.4  : bc6cab1 : Oct 30 2014 07:32:01 UTC on Linux 4.9.4-gentoo (x86_64), built with libpci 3.1.10, GCC 4.8.x-google 20140307 (prerelease), little endian
165
+        generic_disable_writeprotect(): error=-1.
166
+        FAILED
167
+
168
+References
169
+----------
170
+
171
+ * http://dangerousprototypes.com/docs/SPI
172
+ * https://www.winbond.com/resource-files/w25q128fv_revhh1_100913_website1.pdf
173
+ * https://www.pjrc.com/teensy/W25Q128FV.pdf
174
+ * https://learn.sparkfun.com/tutorials/bus-pirate-v36a-hookup-guide
175
+ * https://www.chromium.org/chromium-os/packages/cros-flashrom
176
+ * http://www.tnhh.net/posts/unbricking-chromebook-with-beaglebone.html

+ 141 - 0
kexec.rst

@@ -0,0 +1,141 @@
1
+..
2
+
3
+Setting up kexec
4
+================
5
+
6
+Prerequisites
7
+-------------
8
+
9
+To be able to use kexec and initramfs images, we have to make sure the following options have been enabled in the kernel config:
10
+
11
+.. code::
12
+        :lang: text
13
+
14
+        CONFIG_BLK_DEV_INITRD=y
15
+        CONFIG_RD_GZIP=y
16
+        CONFIG_RD_BZIP2=y
17
+        CONFIG_RD_LZMA=y
18
+        CONFIG_RD_XZ=y
19
+        CONFIG_RD_LZO=y
20
+        CONFIG_RD_LZ4=y
21
+        CONFIG_KEXEC=y
22
+
23
+Building an initramfs
24
+---------------------
25
+
26
+Let's first create the general structure of our initramfs:
27
+
28
+.. code::
29
+        :lang: text
30
+
31
+        mkdir -p /usr/src/initramfs/{bin,dev,etc,lib,lib64,mnt,proc,root,sbin,sys}
32
+
33
+Rather than compiling a lot of the common utilities that can be found in e.g. coreutils, we compile a static version of busybox to install within in our initramfs:
34
+
35
+.. code::
36
+        :lang: text
37
+
38
+        USE="static" emerge busybox
39
+        cp /usr/bin/busybox /usr/src/initramfs/bin/busybox
40
+
41
+In addition to busybox, we will also need kexec-tools to boot our kernel:
42
+
43
+.. code::
44
+        :lang: text
45
+        USE="static" emerge kexec-tools
46
+        cp /usr/sbin/kexec /usr/src/initramfs/sbin/kexec
47
+
48
+If we run ldd on /usr/sbin/kexec, we can also figure out the dependencies that it will need to run:
49
+
50
+.. code::
51
+        :lang: text
52
+
53
+        ldd /usr/sbin/kexec
54
+        cp -r /lib/{libc.so.6,libz.so.1,ld-linux-armhf.so.3} /usr/src/initramfs/lib
55
+
56
+In /usr/src/initramfs/init, we set up the following init script:
57
+
58
+.. code::
59
+        :lang: text
60
+
61
+        #!/bin/busybox sh
62
+
63
+        mount -t proc none /proc
64
+        mount -t sysfs none /sys
65
+        mount -t devtmpfs none
66
+
67
+        busybox sh
68
+
69
+        umount /dev
70
+        exec switch root /mnt/root /sbin/init
71
+
72
+The above script will drop us in a busybox shell session before resuming to switch to the mounted rootfs at /mnt/root.
73
+Also, do make sure that is executable:
74
+
75
+.. code::
76
+        :lang: text
77
+
78
+        chmod +x /usr/src/initramfs/init
79
+
80
+Once everything has set up, we can pack it all into a initramfs as follows:
81
+
82
+.. code::
83
+        :lang: text
84
+
85
+        cd /usr/src/initramfs
86
+        find . -print0 | cpio --null -ov --format=newc | gzip -9 > ~/initramfs.cpio.gz
87
+
88
+Booting a kernel
89
+----------------
90
+
91
+.. code::
92
+        :lang: text
93
+
94
+        cd /usr/src/linux
95
+        kexec --dtb=arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dtb --ramdisk=initramfs.cpio.gz --command-line="console=tty1 rootfs=/dev/mmcblk2p2 rootfstype=ext4 rootwait rw" arch/arm/boot/zImage
96
+
97
+Using kexec-tools to boot a uImage also works.
98
+
99
+Booting u-boot
100
+--------------
101
+
102
+First, we have to clone the u-boot repository and build u-boot:
103
+
104
+.. code::
105
+        :lang: text
106
+
107
+        git clone git://git.denx.de/u-boot.git --depth=1 -b v2017.01
108
+        cd u-boot
109
+        make A20-OLinuXino-Lime2_defconfig
110
+        make
111
+
112
+Once we have built u-boot, we have to pack it up as a uImage, so that kexec can boot it.
113
+However, before we can pack it up, we have to figure out the load address and the entry address for the board that we are trying to target.
114
+For instance, for the Allwinner boards, we can find the load address as follows:
115
+
116
+.. code::
117
+        :lang: text
118
+
119
+        grep CONFIG_SYS_LOAD_ADDR include/configs/sunxi-common.h
120
+        grep CONFIG_SYS_TEXT_BASE include/configs/sunxi-common.h
121
+
122
+In this case, we'll find that the load address and text base are either configured to be ``0x22000000`` and ``0x2a000000`` or ``0x42000000`` and ``0x4a000000`` respectively.
123
+Closer inspection shows that the Allwinner A20 (sun7i) uses the latter two.
124
+After we have found the load address and text base, we can pack up u-boot:
125
+
126
+.. code::
127
+        :lang: text
128
+
129
+        mkimage -A arm -O linux -T kernel -C none -a 0x42000000 -e 0x4a000000 -d u-boot-dtb.bin u-boot.img
130
+
131
+TODO: this boots up to the point where u-boot display a bit of information and then just hangs.
132
+
133
+References
134
+----------
135
+
136
+ * https://wiki.gentoo.org/wiki/Custom_Initramfs
137
+ * https://blogs.s-osg.org/use-mainline-u-boot-non-signed-kernels-exynos-chromebooks/
138
+ * https://www.riscosopen.org/forum/forums/5/topics/350
139
+ * https://github.com/c0d3z3r0/rockboot
140
+ * https://prabagaranvt.blogspot.nl/2012/09/kexec.html
141
+ * http://elinux.org/images/2/2f/ELC-2010-Damm-Kexec.pdf