github.com/google/trillian-examples@v0.0.0-20240520080811-0d40d35cef0e/binary_transparency/firmware/README.md (about)

     1  Firmware Transparency
     2  =====================
     3  
     4  This directory contains a demonstration of applying transparency patterns and
     5  principles to the problem of firmware updates.  In particular it will focus on
     6  making firmware updates for a small compute platform discoverable.
     7  
     8  See below for implementation status.
     9  
    10  Background
    11  ----------
    12  
    13  **Firmware is ubiquitous**; it's in your phone, watch, TV, alarm clock, baby
    14  monitor, WiFi devices, possibly even your lightbulbs if you have LED lamps. In
    15  any given desktop PC there's the BIOS/UEFI type firmware that many people are
    16  familiar with, but there are also scores of other hidden firmware _blobs_
    17  running on small controllers which power things like management engines,
    18  keyboards, network cards, hard-disks/SSDs. The list goes on.
    19  
    20  **Firmware is powerful**, it runs at the highest privilege level possible and
    21  is often the bedrock on which the security story of the devices it powers
    22  depends.
    23  
    24  It is also often almost entirely invisible and inscrutable, and in many cases
    25  has been
    26  [shown to be insecure and vulnerable](https://eclypsium.com/2020/2/18/unsigned-peripheral-firmware).
    27  
    28  Today, the best-in-class vendors who supply the firmware also provide an update
    29  framework which verifies the integrity and authenticity of firmware updates
    30  before allowing them to be installed.
    31  
    32  Even in this _best case_, how do we know that the signed firmware is not
    33  faulty, or even malicious?  What if the signing identity used to assert
    34  authenticity of the firmware is somehow used to sign unintended updates
    35  (whether through outright compromise as in the
    36  [Realtek identity used to sign the Stuxnet worm](https://arstechnica.com/information-technology/2017/11/evasive-code-signed-malware-flourished-before-stuxnet-and-still-does/),
    37  or, perhaps, more subtly via some form of insider risk - be it malicious or
    38  otherwise)?
    39  
    40  How will the _publisher themselves_ even know this has happened?  If they have
    41  been compromised, can they trust their key protection or audit logging?
    42  
    43  How will the consumer of the update know whether they're being given the same
    44  update as all the other devices, or one especially crafted for just a small
    45  subset of folks?
    46  
    47  Firmware Transparency and Discoverability
    48  -----------------------------------------
    49  
    50  Firmware Transparency is a mechanism to ensure that all firmware is
    51  _discoverable_.
    52  This means that the _same list_ of published firmware is visible to the
    53  publisher, the devices which will be updated, and to folks like security
    54  researchers who can use state-of-the-art static analysis and inspection tooling
    55  to analyse them.
    56  
    57  ### Outline
    58  
    59  The goal is to have a system where firmware updates can not be {installed/booted}
    60  unless they have been made discoverable via a verifiable log.
    61  
    62   - [X] Define a [claimant model](https://github.com/google/trillian/tree/master/docs/claimantmodel)
    63         description: [FT Claimant Model](./docs/design/README.md#claimant-model)
    64   - [X] Specify/document a system architecture for that model.
    65   - [X] Come up with some metadata format: [FirmwareMetadata](./api/firmware_metadata.go)
    66   - [X] Build a simple personality around that format.
    67   - [X] Extend personality to also store firmware images.
    68   - [X] Build a simple tool to create metadata given a "boot" image (e.g. Linux
    69       Kernel, WASM binary, etc.), and log it via the personality.
    70   - [X] Figure out a way to package the metadata with the bootable image.
    71   - [X] Build a noddy "device" emulator which enforces logging requirements, and refuses to boot
    72         an image unless all of the following are true:
    73      - [X] the metadata is present.
    74      - [X] the metadata has a "valid" signature
    75      - [X] the boot-image hash matches the one committed do in the metadata.
    76      - [X] a valid STH and inclusion proof for the metatdata is available and
    77            verifies correctly.
    78   - [X] Build a simple "flash" tool which refuses to flash an image to a device
    79         unless all of the boot-time requirements above are satisfied, in
    80         addition to requesting and validating a valid consistency proof between
    81         the previously seen STH and the new STH.
    82   - [X] Flash stores "proof bundle" on device for validation at boot time.
    83   - [X] Build simple monitor to tail the log and dump info from meta-data in realtime.
    84   - [X] Monitor is extended to validate firmware images hash
    85   - [X] Integrated STH Witness support, as an optional feature
    86  
    87  Planned future enhancements:
    88   - [ ] Add support for emulated and real hardware, e.g. via QEmu.
    89  
    90  Running the Demo
    91  ----------------
    92  In running this demo you will take on the role of several different actors within the ecosystem
    93  to see how making firmware discoverable works in practice. You will then take the role of an
    94  attacker trying to install malicious code onto a device, and see how the application of
    95  transparency has made this attack much more expensive.
    96  
    97  During the demo flow you will open several different terminals. It's far easier to use a terminal
    98  that supports tabs in order to do this. The terminals simply make your life easier as different
    99  logical actors have their own terminals in which to perform their actions.
   100  
   101  Prerequisites:
   102  * Install Docker and docker-compose
   103  * Install Go (1.15+)
   104  * Checkout:
   105    * [Trillian](https://github.com/google/trillian)
   106    * [Firmware Transparency (trillian-examples)](https://github.com/google/trillian-examples)
   107  
   108  #### Terminal 1 - Set up Services:
   109  * Open terminal in a directory that you're happy to check out code to:
   110  
   111  ```bash
   112  git checkout https://github.com/google/trillian
   113  git checkout https://github.com/google/trillian-examples
   114  docker-compose -f trillian/examples/deployment/docker-compose.yml -f trillian-examples/binary_transparency/firmware/docker-compose.override.yml up -d personality
   115  ```
   116  
   117  Trillian and the FT server will start in the background and provision a new log.
   118  
   119  #### Terminal 2 - FT monitor
   120  > The monitor "tails" the log, fetching each of the added entries and checking
   121  > for inconsistencies in the structure and unexpected or malicious entries.
   122  
   123  For our demo, we'll scan each firmware binary for the word `H4x0r3d`
   124  and consider that any binary containing that string is a bad one.
   125  
   126  * Open a terminal in the `binary_transparency/firmware` directory, and run
   127    the command below to start a monitor:
   128  
   129  ```bash
   130  go run ./cmd/ft_monitor/ --logtostderr --keyword="H4x0r3d" --state_file=/tmp/ftmon.state
   131  ```
   132  
   133  #### Terminal 3 - Firmware Vendor
   134  The vendor is going to publish a new, legitimate, firmware now.
   135  
   136  * cd to the root of `binary_transparency/firmware` for the following steps:
   137  * We're going to log a new "firmware" build, as the vendor would:
   138  
   139  ```bash
   140  go run cmd/publisher/publish.go --logtostderr --v=2 --timestamp="2020-10-10T15:30:20.10Z" --binary_path=./testdata/firmware/dummy_device/example.wasm --output_path=/tmp/update.ota --device=dummy
   141  ```
   142  
   143    This creates and submits a new firmware manifest to the log, waits for it to be
   144    included, and then builds a firmware update package ("OTA") and writes it out to local disk.
   145  
   146    > :mag_right: Very shortly you should see that the new firmware entry has
   147    > been spotted by the `FT monitor` above.
   148    >
   149    > This is important! If the `Firmware Vendor` is paying attention to the
   150    > contents of the log, they can check that every piece of firmware
   151    > they see logged there is expected and corresponds to a legitimate and
   152    > known-good build.  If they spot something _unexpected_ then they're
   153    > now aware that there is a problem which needs investigation...
   154  
   155  #### Terminal 4 - Device owner
   156  Through the power of scripted narrative, the owner of the target device now
   157  has a firmware update to install (we'll re-use the `/tmp/update.ota` file created
   158  in the last step).
   159  
   160  1. cd to the root of `binary_transparency/firmware` for the following steps:
   161  
   162     Now that we have an update package for our new firmware, we can try flashing
   163     it to a device.
   164  
   165     > :frog: The repo contains a "dummy device" which uses the local disk
   166     > to store the device's state. You'll need to choose and create a directory
   167     > where this dummy device state will live - the instructions below assume
   168     > that is `/tmp/dummy_device', change the path if you're using something different.
   169     >
   170     > ```bash
   171     > mkdir /tmp/dummy_device
   172     > ```
   173  
   174     We'll use the `cmd/flash_tool` to do this flashing.
   175  
   176     > :warning: Note that the first time you do this the "dummy device" will
   177     > have no state and the flashing process will fail.
   178     > It will also fail if you've previously flashed firmware onto the device
   179     > from a different log.
   180     > In both of these cases, you can use the `--force` flag on the `flash_tool`.
   181  
   182     ```bash
   183     go run ./cmd/flash_tool/ --logtostderr --update_file=/tmp/update.ota --device_storage=/tmp/dummy_device --device=dummy # --force if it's the first time
   184     ```
   185  
   186  2. Boot the device.
   187  
   188     We'll boot the device emulator to check that everything is working ok.
   189     The "ROM" on the dummy device verifies the integrity of the firmware and
   190     proofs stored on the device.
   191  
   192      ```bash
   193      go run ./cmd/emulator/dummy --logtostderr --dummy_storage_dir=/tmp/dummy_device
   194      ```
   195  
   196  > :frog: Because both the `flash_tool` and the device itself verifies the
   197  > correctness of the inclusion proofs, they are convinced that the firmware
   198  > is now _discoverable_ - anybody looking at the contents of the log _also_
   199  > knows about its existence: this doesn't guarantee that the firmware is
   200  > _"good"_, but we know at least that it can't be a covert targeted attack, _and_
   201  > we can assume that the `Firmware vendor` is aware of it too.
   202  
   203  #### Terminal 666 - The Hacker :shipit::computer:
   204  _"Nice system you've got there. Let's test it..."_
   205  
   206  * cd to the root of `binary_transparency/firmware` for the following steps.
   207  
   208  :firecracker: The hacker has a malicious firmware they want to install on our
   209  device. It's in `testdata/firmware/dummy_device/hacked.wasm`.
   210  
   211  1. Write malicious firmware directly onto the device.
   212  
   213  Let's imagine the hacker has access to our device, they're going to write their
   214  malicious firmware directly over the top of our device's firmware:
   215  
   216  ```bash
   217  cp testdata/firmware/dummy_device/hacked.wasm /tmp/dummy_device/firmware.bin
   218  echo "mwuhahahaha :eyes:"
   219  ```
   220  
   221  Let's watch as the device owner turns on their device in the next step...
   222  
   223  #### Terminal 4 - Device owner
   224  The device owner wants to use their device, however, unbeknownst to them it's
   225  been HACKED!
   226  
   227  Start up the device:
   228  
   229  ```bash
   230  go run ./cmd/emulator/dummy --logtostderr --dummy_storage_dir=/tmp/dummy_device
   231  ```
   232  
   233  We should see that the device refuses to boot, with an error similar to this:
   234  
   235  ```
   236  dummy_emu.go:41] ROM: "failed to verify bundle: firmware measurement does not match metadata (0xefb19feba9ea0e0d5de73ac16d8aa9c4ceb092ecd13eab5548f49a61e85c367a2f2c8ce1eb36b67e1407148406705e67663dc5b6d3f05a45475f6e4a2b69e285 != 0xbf2f21936b66a0665883716ea4b1ceda609304ad76dd48f6423128bc36d4cb0fb5effaa9c1f2e328a5cfc25d2cb89a337d4285a8bc3e22dbb99bddbed19e7095)"
   237  ```
   238  
   239  > :frog: This happened because the device _measured_ the firmware and compared that
   240  > with what the firmware manifest claimed the expected measurement should be.
   241  > Since the device firmware had been overwritten, they didn't match and the
   242  > device refused to boot.
   243  >
   244  > Back to the drawing board, hacker!
   245  
   246  #### Terminal 666 - The Hacker :shipit::computer:
   247  
   248  We need to update the manifest on the device with the correct measurement for our hacked firmware.
   249  Run the following command:
   250  
   251  ```bash
   252  go run ./cmd/hacker/modify_bundle \
   253     --device dummy \
   254     --binary ./testdata/firmware/dummy_device/hacked.wasm \
   255     --input /tmp/dummy_device/bundle.json \
   256     --output /tmp/dummy_device/bundle.json \
   257     --sign=false
   258  ```
   259  
   260  Let's watch as the device owner turns on their device in the next step...
   261  
   262  #### Terminal 4 - Device owner
   263  
   264  Start the device:
   265  
   266  ```bash
   267  go run ./cmd/emulator/dummy --logtostderr --dummy_storage_dir=/tmp/dummy_device
   268  ```
   269  
   270  and _again_, even though the device now gets past the firmware measurement check
   271  we should see that the device still refuses to boot, with an error similar to:
   272  
   273  ```
   274  F1215 17:47:06.449540 1724707 dummy_emu.go:41] ROM: "failed to verify bundle: failed to verify signature on SignedStatement: failed to verify signature crypto/rsa: verification error"
   275  exit status 1
   276  ```
   277  
   278  #### Terminal 666 - The Hacker :shipit::computer:
   279  
   280  Ok, this time we'll "steal" the key and use it to sign our malicious firmware.
   281  This is equivalent to the status-quo today.
   282  
   283  Run the following command:
   284  
   285  ```bash
   286  go run ./cmd/hacker/modify_bundle \
   287     --device dummy \
   288     --binary ./testdata/firmware/dummy_device/hacked.wasm \
   289     --input /tmp/dummy_device/bundle.json \
   290     --output /tmp/dummy_device/bundle.json \
   291     --sign=true
   292  ```
   293  
   294  Let's watch as the device owner turns on their device in the next step...
   295  
   296  #### Terminal 4 - Device owner
   297  
   298  Start the device:
   299  
   300  ```bash
   301  go run ./cmd/emulator/dummy --logtostderr --dummy_storage_dir=/tmp/dummy_device
   302  ```
   303  
   304  We've got past the signature check, but now there's another error:
   305  
   306  ```
   307  dummy_emu.go:41] ROM: "failed to verify bundle: invalid inclusion proof in bundle: calculated root:\n[202 202 214 35 92 129 74 43 92 63 27 232 69 79 93 26 187 86 24 174 32 49 53 19 122 252 252 241 139 226 122 79]\n does not match expected root:\n[186 61 229 40 73 60 245 168 87 2 6 107 225 25 186 169 85 12 74 158 126 168 255 168 27 149 245 138 27 211 67 234]"
   308  exit status 1
   309  ```
   310  
   311  > :frog: This message indicates that the device was unable to verify that the
   312  > firmware manifest was included in the log using the inclusion proof and checkpoint
   313  > which are present in the `bundle.json`.
   314  > This makes sense - the modified firmware manifest _hasn't_ been included!
   315  >
   316  > Think again, hacker!
   317  
   318  #### Terminal 666 - The Hacker :shipit::computer:
   319  
   320  The *only* way we're going to get the hacked firmware onto the device
   321  is to have a valid inclusion proof and checkpoint from the log which
   322  covers the new firmware manifest.
   323  
   324  Let's have the hacker break into the firmware vendor's offices and
   325  add their modified manifest+firmware to the log...
   326  
   327  ```bash
   328  go run cmd/publisher/publish.go --logtostderr --v=2 --timestamp="2020-10-10T23:00:00.00Z" --binary_path=./testdata/firmware/dummy_device/hacked.wasm --output_path=/tmp/bad_update.ota --device=dummy
   329  ```
   330  
   331  > :frog: However, notice that the `FT Monitor` has spotted the firmware!
   332  > Now the firmware vendor knows they have been compromised and can take action. :police:
   333  >
   334  > If the firmware vendor is complicit in the attack, then all is still not lost...
   335  > Notice that the FT monitor has detected the malware in the new firmware too:
   336  > ```
   337  >    Malware detected matched pattern H4x0r3d
   338  > ```
   339  >
   340  > Anybody else running a monitor also knows that malicious firmware has been
   341  > logged and can raise the alarm.
   342  
   343  
   344  Further Work: Annotations and Verifiable Summaries
   345  --------------------------------------------------
   346  
   347  We have seen how to publish firmware and its metadata to a log, and how this can be used by firmware readers: clients flashing the firmware, and monitors scanning the firmware.
   348  Having all parties seeing the same view of the available data sets the foundation for a secure system, but making clients aware of bad firmware cannot be done only with the tools we have above.
   349  
   350  The [ftmap README](fmd/../cmd/ftmap/README.md) outlines a verifiable solution to this problem.
   351  There are 2 key changes from the solution above:
   352    * In addition to firmware & metadata, the log also accepts annotations about firmware already in the log
   353    * A Verifiable Map is built from the log, which aggregates each piece of firmware with the annotations for it
   354  
   355  Clients can then use this verifiable map to efficiently discover all annotations about a piece of firmware before they rely on it.